/*
* Copyright (C) 2020 ~ 2023 chaigec All Rights Reserved.
*
* Author:     chaigec <chaigec@163.com>
* Maintainer: chaigec <chaigec@163.com>

 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
*/

#include "MkGb28181Server.h"
#include "MkGb28181ServerConfig.h"
#include <MkEvent/MkEventPool.h>
#include <MkGb28181/MkGbPtz.h>
#include <MkEvent/MkTimer.h>
#include <MkEvent/MkEvent.h>
#include <MkHttpHooker/MkHttpHooker.h>
#include <MkGb28181/MkGbUtil.h>
#include <MkHttp/MkHttpSession.h>
#include <MkUtil/MkUtil.h>
#include <MkUtil/MkFile.h>
#include <MkUtil/MkLog.h>
#include <MkUtil/MkMd5.h>
#include <MkSdp/MkSdp.h>
#include <signal.h>

#define StringAll           "All"
#define ExeName             "MkGbServer"
#define HttpPort            "http.port"
#define HttpUserName        "http.userName"
#define HttpPassword        "http.password"
#define HttpWsUrl           "http.wsUrl"
#define HttpApiUriPrefix    "http.apiUriPrefix"
#define HttpKeepAliveSec    "http.keepAliveSec"
#define HttpMaxKeepAliveReq "http.maxKeepAliveReq"
#define GbServerId          "gb.serverId"
#define GbRealm             "gb.realm"
#define GbPort              "gb.port"
#define GbHost              "gb.host"
#define GbMappingPort       "gb.mappingPort"
#define GbMappingHost       "gb.mappingHost"
#define GbRegisterExpries   "gb.registerExpries"
#define GbSubscribeExpries  "gb.subscribeExpries"
#define GbAutoSubCatalog    "gb.autoSubscribeCatalog"
#define GbAutoPtzPosition   "gb.autoSubscribePTZPosition"
#define GbAutoSubMoPos      "gb.autoSubscribeMobilePosition"
#define GbMoPosInterval     "gb.mobilePositionInterval"
#define GbDirectPlayback    "gb.directPlayback"
#define HttpHookerUserName  "httpHooker.userName"
#define HttpHookerPassword  "httpHooker.password"
#define HttpHookerParam     "httpHooker.param"
#define HttpHookerUrl       "httpHooker.url"
#define TcpUnSendMs         "tcp.unSendMilliSec"
#define TcpUnSendMB         "tcp.unSendMB"
#define UdpUnSendMs         "udp.unSendMilliSec"
#define UdpUnSendMB         "udp.unSendMB"
CMkGbServer *g_pGbServer = nullptr;
CMkGbServer::CMkGbServer(CMkEventPool* pEventPool, CMkTimer* pTimer)
    : CMkHttpApi(pEventPool, pTimer)
    , m_pGb28181(new CMkGb28181(pEventPool, pTimer))
    , m_pHttpHooker(new CMkHttpHooker(pEventPool, pTimer))
    , m_TalkSourceId("34020000001360000001")
    , m_RegisterDelaySec(60)
    , m_bReboot(FALSE)
{
    g_pGbServer = this;
    m_MapNotifyMsgType[MkNotifyActionAlarm] = "Alarm";
    m_MapNotifyMsgType[MkNotifyActionDeviceOnline] = "DeviceOnline";
    m_MapNotifyMsgType[MkNotifyActionCatalog] = "Catalog";
    m_MapNotifyMsgType[MkNotifyActionPlayEnd] = "PlayEnd";
    m_MapNotifyMsgType[MkNotifyActionPlayInfo] = "PlayInfo";
    m_MapPlayControl["Pause"] = MkGbPlayControlPause;
    m_MapPlayControl["ReStore"] = MkGbPlayControlReStore;
    m_MapPlayControl["Seek"] = MkGbPlayControlSeek;
    m_MapPlayControl["SetSpeed"] = MkGbPlayControlSetSpeed;


    AddParser("version", MkHttpMethodGet, &CMkGbServer::GetVersionParse);
    AddParser("websocket-access-key", MkHttpMethodGet, &CMkGbServer::GetWebSocketAccessKeyParse);
    AddParser("config", MkHttpMethodGet, &CMkGbServer::GetConfigParse);
    AddParser("config", MkHttpMethodPut, &CMkGbServer::ChangeConfigParse);
    AddParser("http-hooker", MkHttpMethodGet, &CMkGbServer::GetHttpHookerParse);
    AddParser("http-hooker", MkHttpMethodPut, &CMkGbServer::ChangeHttpHookerParse);

    AddParser("online-device", MkHttpMethodGet, &CMkGbServer::GetOnlineDeviceParse);
    AddParser("device-query", MkHttpMethodGet, &CMkGbServer::DeviceQueryParse);
    AddParser("device-control", MkHttpMethodPut, &CMkGbServer::DeviceControlParse);
    AddParser("device-config", MkHttpMethodPut, &CMkGbServer::DeviceConfigParse);
    AddParser("catalog", MkHttpMethodPut, &CMkGbServer::CatalogChangeParse);

    AddParser("play", MkHttpMethodPost, &CMkGbServer::StartPlayParse);
    AddParser("play", MkHttpMethodDelete, &CMkGbServer::StopPlayParse);
    AddParser("play", MkHttpMethodPut, &CMkGbServer::PlayControlParse);

    AddParser("decode", MkHttpMethodPost, &CMkGbServer::StartDecodeParse);
    AddParser("decode", MkHttpMethodDelete, &CMkGbServer::StopDecodeParse);

    AddParser("up-server", MkHttpMethodGet, &CMkGbServer::GetUpServerParse);
    AddParser("up-server", MkHttpMethodPost, &CMkGbServer::AddUpServerParse);
    AddParser("up-server", MkHttpMethodDelete, &CMkGbServer::DeleteUpServerParse);

    AddParser("hooker", MkHttpMethodPost, &CMkGbServer::DefaultCallbackParse);
    MkString strKey;
    CMkUtil::CreateRandomString(Len16, strKey);
    SetWebSocketAccessKey(strKey);
}

Uint32 CMkGbServer::Init(int argc, char** argv)
{
#ifndef _WIN32
    signal(SIGPIPE, SIG_IGN);  //ignore sigpipe
#endif
    signal(SIGINT, [](int sig) {
        if (sig == SIGINT && g_pGbServer->GetTimer()) {
            g_pGbServer->GetTimer()->LoopBreak();
        }
    });// set ctrl +c
    MkLogChangeLevel(LOG_DEBUG);
    MkLogInitLevel(ExeName, TO_SCREEN | TO_FILE);
    Uint32 ErrorCode = NoneError;
    do {
        m_bReboot = FALSE;
        ErrorCode = Start();
        MkCheckErrorLog(ErrorCode, "start gb server failed\n");
        GetTimer()->Dispatch();
        CMkThread::ThreadSleep(1000); //wait all stopped
        Stop();
    } while (m_bReboot);
    return NoneError;
}


Uint32 CMkGbServer::Start()
{
    Uint32 ErrorCode = NoneError;
    ErrorCode = ReadConfig();
    MkCheckErrorLog(ErrorCode, "read config failed\n");
    CMkSocket::SetTcpSendFailCumulativeMs(m_ConfigIni.GetProfileUint32(TcpUnSendMs, 3000));
    CMkSocket::SetTcpSendFailCumulativeMB(m_ConfigIni.GetProfileUint32(TcpUnSendMB, 20));
    CMkSocket::SetUdpSendFailCumulativeMB(m_ConfigIni.GetProfileUint32(UdpUnSendMB, 20));
    CMkSocket::SetUdpSendFailCumulativeMs(m_ConfigIni.GetProfileUint32(UdpUnSendMs, 3000));
    ErrorCode = StartServer(m_ConfigIni.GetProfileUint32(HttpPort, 80));
    MkInfoLog("start http server:%d success\n", m_ConfigIni.GetProfileUint32(HttpPort, 80));
    SetUserPass(m_ConfigIni.GetProfileString(HttpUserName), m_ConfigIni.GetProfileString(HttpPassword));
    SetApiUriPrefix(m_ConfigIni.GetProfileString(HttpApiUriPrefix, "/api/v1/"));
    SetWebSocketPath(m_ConfigIni.GetProfileString(HttpWsUrl, "/ws/notify"));
    SetKeepAliveSeconds(m_ConfigIni.GetProfileUint32(HttpKeepAliveSec, 60));
    SetMaxKeepAliveRequest(m_ConfigIni.GetProfileUint32(HttpMaxKeepAliveReq, 1000));
    m_pHttpHooker->SetUserPass(GetUserName(), GetPassword());
    m_pHttpHooker->SetHttpUrl(m_ConfigIni.GetProfileString(HttpHookerUrl, "http://127.0.0.1/api/v1/hooker"));
    MkGbStartParam Param;
    Param.LocalHost = m_ConfigIni.GetProfileString(GbHost, "");
    Param.LocalPort = m_ConfigIni.GetProfileUint32(GbPort, 5060);
    Param.SipId = m_ConfigIni.GetProfileString(GbServerId);
    Param.SipRealm = m_ConfigIni.GetProfileString(GbRealm);
    Param.MappingHost = m_ConfigIni.GetProfileString(GbMappingHost);
    Param.MappingPort = m_ConfigIni.GetProfileUint32(GbMappingPort);
    Param.RegisterExpires = m_ConfigIni.GetProfileUint32(GbRegisterExpries);
    Param.SubscribeExpires = m_ConfigIni.GetProfileUint32(GbSubscribeExpries);
    ErrorCode = m_pGb28181->Start(Param, [this](const CMkGbRequest* pGbReq, const MkGbResponseCallback& Cb) {
        return OnGbRequest(pGbReq, Cb);
    });
    MkCheckErrorLog(ErrorCode, "start gb failed\n");

    RegisterAllUpServer();
    GetTimer()->AddTimer([this]() {
        OnDeviceCheckTimer();
    }, 5000, m_DeviceCheckTimer);

    MkString strVersion;
    GetVersion(strVersion);
    MkInfoLog("start mk gb server version:%s\n", strVersion.c_str());
    return NoneError;
}

Uint32 CMkGbServer::Stop()
{
    m_pGb28181->Stop();
    return StopServer();
}

Uint32 CMkGbServer::ReadConfig()
{
    MkString ConfigPath;
    CMkFile::GetConfigPath(ConfigPath);
    if (!CMkFile::IsDir(ConfigPath)) {
        CMkFile::MakeDir(ConfigPath);
    }
    MkString ConfigFile = ConfigPath + "/" + ExeName + ".ini";
    MkString UpSvrJsonFile = ConfigPath + "/UpSvr.Json";
#ifdef MkUt
    CMkFile::DeleteLocalFile(ConfigFile);
#endif
    Uint32 ErrorCode = m_ConfigIni.LoadFile(ConfigFile);
    if (NoneError != ErrorCode) {
#ifdef MkUt
        m_ConfigIni.SetProfileString(HttpUserName, "admin");
        m_ConfigIni.SetProfileString(HttpPassword, "admin");
        m_ConfigIni.SetProfileString(HttpWsUrl, "/ws/notify");
        m_ConfigIni.SetProfileString(HttpApiUriPrefix, "/api/v1/");
        m_ConfigIni.SetProfileUint32(HttpKeepAliveSec, 60);
        m_ConfigIni.SetProfileUint32(HttpMaxKeepAliveReq, 1000);
        m_ConfigIni.SetProfileString(GbServerId, "34020000002020000001");
        m_ConfigIni.SetProfileString(GbRealm, "3402000000");
        m_ConfigIni.SetProfileString(GbHost, "");
        while (1) {
            Uint32 RandomPort = CMkUtil::GetRandomNumber() & 0xFFFF;
            if (NoneError == CMkUtil::CheckTcpIsUseAbled(RandomPort)
                && NoneError == CMkUtil::CheckUdpIsUseAbled(RandomPort)) {
                m_ConfigIni.SetProfileUint32(GbPort, RandomPort);
                break;
            }
        }
        m_ConfigIni.SetProfileString(GbMappingHost, "");
        m_ConfigIni.SetProfileUint32(GbMappingPort, 0);
        m_ConfigIni.SetProfileUint32(TcpUnSendMs, 3000);
        m_ConfigIni.SetProfileUint32(TcpUnSendMB, 20);
        m_ConfigIni.SetProfileUint32(UdpUnSendMs, 3000);
        m_ConfigIni.SetProfileUint32(UdpUnSendMB, 20);
#else
        m_ConfigIni.SetProfileUint32(HttpPort, 80);
        m_ConfigIni.SetProfileString(HttpUserName, "admin");
        m_ConfigIni.SetProfileString(HttpPassword, "admin");
        m_ConfigIni.SetProfileString(HttpWsUrl, "/ws/notify");
        m_ConfigIni.SetProfileString(HttpApiUriPrefix, "/api/v1/");
        m_ConfigIni.SetProfileUint32(HttpKeepAliveSec, 60);
        m_ConfigIni.SetProfileUint32(HttpMaxKeepAliveReq, 1000);
        m_ConfigIni.SetProfileString(GbServerId, "34020000002000000001");
        m_ConfigIni.SetProfileString(GbRealm, "3402000000");
        m_ConfigIni.SetProfileString(GbHost, "");
        m_ConfigIni.SetProfileUint32(GbPort, 5060);
        m_ConfigIni.SetProfileString(GbMappingPort, "");
        m_ConfigIni.SetProfileUint32(GbMappingHost, 0);
        m_ConfigIni.SetProfileString(HttpHookerUserName, "admin");
        m_ConfigIni.SetProfileString(HttpHookerPassword, "admin");
        m_ConfigIni.SetProfileString(HttpHookerParam, "token=123&param=123");
        m_ConfigIni.SetProfileString(HttpHookerUrl, "http://127.0.0.1/api/v1/hooker");
        m_ConfigIni.SetProfileUint32(TcpUnSendMs, 3000);
        m_ConfigIni.SetProfileUint32(TcpUnSendMB, 20);
        m_ConfigIni.SetProfileUint32(UdpUnSendMs, 3000);
        m_ConfigIni.SetProfileUint32(UdpUnSendMB, 20);
        m_ConfigIni.SetProfileUint32(GbRegisterExpries, 3600);
        m_ConfigIni.SetProfileUint32(GbSubscribeExpries, 3600);
        m_ConfigIni.SetProfileBoolean(GbAutoSubCatalog, TRUE);
        m_ConfigIni.SetProfileBoolean(GbAutoSubMoPos, TRUE);
        m_ConfigIni.SetProfileBoolean(GbAutoPtzPosition, TRUE);
        m_ConfigIni.SetProfileBoolean(GbDirectPlayback, TRUE);
        m_ConfigIni.SetProfileUint32(GbMoPosInterval, 30);
#endif
        ErrorCode = m_ConfigIni.WriteFile(ConfigFile);
    }
    MkString StringUpSvrJson;
    ErrorCode = CMkFile::ReadFileBuffer(UpSvrJsonFile, StringUpSvrJson);
    if (NoneError == ErrorCode) {
        Json::Value JsonUpSvr;
        try {
            Json::CharReaderBuilder b;
            Json::CharReader *reader(b.newCharReader());
            if (!reader) {
                ErrorCode = MallocFailed;
            } else {
                MkString errs;
                reader->parse(StringUpSvrJson.c_str(), StringUpSvrJson.c_str() + StringUpSvrJson.size(), &JsonUpSvr, &errs);
                delete reader;

                for (Json::ArrayIndex i = 0; i < JsonUpSvr.size(); i++) {
                    MkUpGbServer GbSvr;
                    GbSvr.GbSvrId = JsonUpSvr[i]["ServerId"].asString();
                    GbSvr.GbSvrRealm = JsonUpSvr[i]["ServerRealm"].asString();
                    GbSvr.GbSvrHost = JsonUpSvr[i]["ServerHost"].asString();
                    GbSvr.GbSvrPort = JsonUpSvr[i]["ServerPort"].asInt();
                    GbSvr.HBInterval = JsonUpSvr[i]["HBInterval"].asInt();
                    GbSvr.HBCount = JsonUpSvr[i]["HBCount"].asInt();
                    GbSvr.Expires = JsonUpSvr[i]["Expires"].asInt();
                    GbSvr.bTcp = JsonUpSvr[i]["TcpSip"].asBool();
                    m_GbServerLock.WLock();
                    m_MapUpGbServer[GbSvr.GbSvrId] = GbSvr;
                    m_GbServerLock.WUnlock();
                }
            }
        } catch (Json::Exception &e) {
            MkErrorLog("body:%s\n", StringUpSvrJson.c_str());
            MkErrorLog("json parse error:%s\n", e.what());
        }
    }
    return NoneError;
}

Uint32 CMkGbServer::WriteUpSvrJson()
{
    MkString ConfigPath;
    CMkFile::GetConfigPath(ConfigPath);
    MkString UpSvrJsonFile = ConfigPath + "/UpSvr.Json";
    Json::Value JsonUpSvr;
    m_GbServerLock.RLock();
    MkMap<MkString, MkUpGbServer>::iterator it = m_MapUpGbServer.begin();
    for (int i = 0; it != m_MapUpGbServer.end(); it++, i++) {
        JsonUpSvr[i]["ServerId"] = it->second.GbSvrId;
        JsonUpSvr[i]["ServerRealm"] = it->second.GbSvrRealm;
        JsonUpSvr[i]["ServerHost"] = it->second.GbSvrHost;
        JsonUpSvr[i]["ServerPort"] = it->second.GbSvrPort;
        JsonUpSvr[i]["HBInterval"] = it->second.HBInterval;
        JsonUpSvr[i]["HBCount"] = it->second.HBCount;
        JsonUpSvr[i]["Expires"] = it->second.Expires;
        JsonUpSvr[i]["TcpSip"] = it->second.bTcp;
    }
    m_GbServerLock.RUnlock();
    CMkFile::WriteFileBuffer(UpSvrJsonFile, JsonUpSvr.toStyledString());
    return NoneError;
}

Uint32 CMkGbServer::GetVersion(MkString& Version)
{
    Version = MkString(MkGbServerVersion) + "_build(" + MkString(__DATE__) + " " + MkString(__TIME__) + ") GBT28181-2022";
    return NoneError;
}

Uint32 CMkGbServer::AddParser(const MkString& Path, const MkHttpMethod& Method, const GbParser& Parser)
{
    Uint32 ErrorCode = NoneError;
    switch (Method) {
    case MkHttpMethodGet:
        m_MapGetParser[Path] = Parser;
        break;
    case MkHttpMethodPost:
        m_MapPostParser[Path] = Parser;
        break;
    case MkHttpMethodPut:
        m_MapPutParser[Path] = Parser;
        break;
    case MkHttpMethodDelete:
        m_MapDeleteParser[Path] = Parser;
        break;
    default:
        ErrorCode = UnSupported;
        break;
    }
    return ErrorCode;
}

Uint32 CMkGbServer::RegisterAllUpServer()
{
    m_GbServerLock.RLock();
    MkMap<MkString, MkUpGbServer>::iterator it = m_MapUpGbServer.begin();
    for (; it != m_MapUpGbServer.end(); it++) {
        m_pGb28181->AddRouter(it->second.GbSvrId, it->second.GbSvrRealm, it->second.GbSvrHost, it->second.GbSvrPort, it->second.bTcp);
        CMkGbDeviceAuthorRequest Req;
        Req.m_RouterId = it->second.GbSvrId;
        Req.m_DstId = it->second.GbSvrId;
        Req.m_Realm = it->second.GbSvrRealm;
        Req.m_Expires = it->second.Expires;
        RegisterUpServer(Req);
    }
    m_GbServerLock.RUnlock();
    return NoneError;
}

Uint32 CMkGbServer::OnGbRequest(const CMkGbRequest* pGbReq, const MkGbResponseCallback& Cb)
{
    Uint32 ErrorCode = NoneError;
    switch (pGbReq->m_RequestType) {
    case MkGbRequestDeviceAuthor:
        ErrorCode = OnGbDeviceAuthor(pGbReq, Cb);
        break;
    case MkGbRequestMessage:
        ErrorCode = OnGbMessageRequest(dynamic_cast<const CMkGbMessageRequest*>(pGbReq), Cb);
        break;
    case MkGbRequestNotify:
        ErrorCode = OnGbNotifyReqeust(dynamic_cast<const CMkGbNotifyRequest*>(pGbReq), Cb);
        break;
    case MkGbRequestSubscribe:
        ErrorCode = OnGbSubscribeRequest(dynamic_cast<const CMkGbSubscribeRequest*>(pGbReq), Cb);
        break;
    case MkGbRequestInvite:
        ErrorCode = OnGbInviteRequest(dynamic_cast<const CMkGbInviteReqeust*>(pGbReq), Cb);
        break;
    case MkGbRequestBye:
        ErrorCode = OnGbByeRequest(dynamic_cast<const CMkGbByeReqeust*>(pGbReq), Cb);
        break;
    default:
        break;
    }
    return ErrorCode;
}

Uint32 CMkGbServer::OnGbDeviceAuthor(const CMkGbRequest* pGbReq, const MkGbResponseCallback& Cb)
{
    Uint32 ErrorCode = NoneError;
    CMkGbDeviceAuthorRequest Req;
    const CMkGbDeviceAuthorRequest *pAuthorReq = dynamic_cast<const CMkGbDeviceAuthorRequest*>(pGbReq);
    if (!pAuthorReq) {
        return InvalidParams;
    }
    Req = *pAuthorReq;
    ErrorCode = DeviceAuthorRequest(Req, [this, Req, Cb](Uint32 ErrorCode, const Json::Value &ResBody) {
        CMkGbDeviceAuthorResponse Res;
        Res.m_bRedirect = ResBody["Redirect"].asBool();
        if (Res.m_bRedirect) {
            Res.m_RedirectHost = ResBody["RedirectHost"].asString();
            Res.m_RedirectPort = ResBody["RedirectPort"].asInt();
            Res.m_RedirectId = ResBody["RedirectID"].asString();
        }
        Cb(ErrorCode, &Res);

        if (!Res.m_bRedirect && NoneError == ErrorCode) {
            DeviceAuthorSuccess(Req.m_RegisterId, Req.m_FromId, Req.m_DeviceHost, Req.m_DevicePort, 0 != Req.m_Expires);
        }
    });

    return ErrorCode;
}

Uint32 CMkGbServer::OnGbMessageRequest(const CMkGbMessageRequest* pGbReq, const MkGbResponseCallback& Cb)
{
    if (!pGbReq) {
        return InvalidParams;
    }
    Uint32 ErrorCode = NoneError;
    if ("Notify" == pGbReq->m_MessageType) {
        if ("Keepalive" == pGbReq->m_CmdType) {
            ErrorCode = OnGbDeviceKeepAlive(pGbReq, Cb);
        } else {
            CMkGbMessageResponse Res;
            Res.m_Message.MainParam["Result"] = "OK";
            Cb(NoneError, &Res);
            Json::Value Body;
            PacketGbMessageToJson(pGbReq->m_Message, Body);
            Body["DeviceID"] = pGbReq->m_DstId;
            ErrorCode = NotifyMsg(pGbReq->m_CmdType, Body); //notify to all web socket
            NotifyDeviceNotifyAllUpServer(pGbReq);   //notify to all up server
        }
    } else if ("Query" == pGbReq->m_MessageType)  //up server query
    {
        if ("Catalog" == pGbReq->m_CmdType) {
            ErrorCode = CatalogRequest([this, Cb](Uint32 ErrorCode, const Json::Value &ResBody) {
                CMkGbMessageResponse Res;
                ParseJsonContentToGbMessage(ResBody, Res.m_Message);
                Cb(ErrorCode, &Res);
            });
        } else {
            CMkGbMessageRequest Req = *pGbReq;
            ErrorCode = GetDevice(Req.m_DstId, Req.m_RouterId);
            MkCheckErrorLog(ErrorCode, "get req child id:%s invalid\n", Req.m_DstId.c_str());
            return m_pGb28181->MessageRequest(Req, [this, Cb](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {
                Cb(NoneError, pGbRes);
            });
        }
    } else if ("Control" == pGbReq->m_MessageType) {
        CMkGbMessageRequest Req = *pGbReq;
        ErrorCode = GetDevice(Req.m_DstId, Req.m_RouterId);
        MkCheckErrorLog(ErrorCode, "get req child id:%s invalid\n", Req.m_DstId.c_str());
        ErrorCode = m_pGb28181->MessageRequest(Req, [this, Cb](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {
            Cb(NoneError, pGbRes);
        });
    }
    return ErrorCode;
}

Uint32 CMkGbServer::OnGbNotifyReqeust(const CMkGbNotifyRequest* pGbReq, const MkGbResponseCallback& Cb)
{
    CMkGbNotifyResponse Res;
    Res.m_Message.MainParam["Result"] = "OK";
    Cb(NoneError, &Res);
    Json::Value Body;
    PacketGbMessageToJson(pGbReq->m_Message, Body);
    Body["DeviceID"] = pGbReq->m_DstId;
    NotifyMsg(pGbReq->m_CmdType, Body);  //notify to web socket

    MkVectorString VecSubscribeId;
    m_GbServerLock.RLock();
    MkMap<MkString, MkUpGbServer>::iterator it = m_MapUpGbServer.begin();
    for (; it != m_MapUpGbServer.end(); it++) {
        MkMapString::iterator itStr;
        if ("PTZPosition" == pGbReq->m_CmdType) {
            itStr = it->second.MapUpPtzPositionSubscribe.find(pGbReq->m_DstId);
            if (itStr != it->second.MapUpPtzPositionSubscribe.end()
                && !itStr->second.empty()) {
                VecSubscribeId.push_back(itStr->second);
            }
        } else if ("MobilePosition" == pGbReq->m_CmdType) {
            itStr = it->second.MapUpMobilePositionSubscirbe.find(pGbReq->m_DstId);
            if (itStr != it->second.MapUpMobilePositionSubscirbe.end()
                && !itStr->second.empty()) {
                VecSubscribeId.push_back(itStr->second);
            }
        } else if ("Catalog" == pGbReq->m_CmdType) {
            if (!it->second.CatalogSubscribeId.empty()) {
                VecSubscribeId.push_back(it->second.CatalogSubscribeId);
            }
        }
    }
    m_GbServerLock.RUnlock();
    MkVectorString::iterator itVec = VecSubscribeId.begin();
    for (; itVec != VecSubscribeId.end(); itVec++) {
        CMkGbNotifyRequest NotifyReq = *pGbReq;
        NotifyReq.m_SubscribeId = *itVec;
        m_pGb28181->NotifyRequest(NotifyReq, nullptr);
    }

    return NoneError;
}

Uint32 CMkGbServer::OnGbSubscribeRequest(const CMkGbSubscribeRequest* pGbReq, const MkGbResponseCallback& Cb)
{
    if (!pGbReq) {
        return InvalidParams;
    }
    m_GbServerLock.WLock();
    MkMap<MkString, MkUpGbServer>::iterator it = m_MapUpGbServer.find(pGbReq->m_FromId);
    if (it != m_MapUpGbServer.end()) {
        if ("PTZPosition" == pGbReq->m_CmdType) {
            it->second.MapUpPtzPositionSubscribe[pGbReq->m_DstId] = pGbReq->m_SubscribeId;
        } else if ("MobilePosition" == pGbReq->m_CmdType) {
            it->second.MapUpMobilePositionSubscirbe[pGbReq->m_DstId] = pGbReq->m_SubscribeId;
        } else if ("Catalog" == pGbReq->m_CmdType) {
            it->second.CatalogSubscribeId = pGbReq->m_SubscribeId;
        }
    }
    m_GbServerLock.WUnlock();
    CMkGbResponse Res;
    Res.m_Message.MainParam["Result"] = "OK";
    Cb(NoneError, &Res);
    return NoneError;
}

Uint32 CMkGbServer::OnGbInviteRequest(const CMkGbInviteReqeust* pGbReq, const MkGbResponseCallback& Cb)
{
    if (!pGbReq) {
        return InvalidParams;
    }
    MkString DeviceId;
    Uint32 ErrorCode = GetDevice(pGbReq->m_DstId, DeviceId);
    MkCheckErrorLog(ErrorCode, "get device info failed\n");
    MkString InviteSession = pGbReq->m_SessionId;
    if (!CMkUtil::BeginByString(pGbReq->m_SubjectSource, pGbReq->m_DstId + ":0")
        && m_ConfigIni.GetProfileBoolean(GbDirectPlayback)) {
        MkString Subject = pGbReq->m_SubjectSource + "," + DeviceId + ":1" + std::to_string(CMkUtil::GetRandomNumber());
        return m_pGb28181->InviteRequest(DeviceId, pGbReq->m_DstId, Subject, pGbReq->m_OfferSdp, [this, InviteSession, Cb](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {
            const CMkGbInviteResponse* pInviteRes = dynamic_cast<const CMkGbInviteResponse*>(pGbRes);
            if (NoneError == ErrorCode && pInviteRes) {
                m_UpPlayLock.WLock();
                m_MapUpPlay[InviteSession] = pInviteRes->m_SessionId;
                m_UpPlayLock.WUnlock();
            }
            Cb(ErrorCode, pGbRes);
        });
    }

    CMkSdp Sdp;
    ErrorCode = Sdp.ParseContent(pGbReq->m_OfferSdp);
    MkCheckErrorLog(ErrorCode, "sdp:%s parse failed\n", pGbReq->m_OfferSdp.c_str());

    MkString OfferSdp = pGbReq->m_OfferSdp;
    MkString ChannelId = pGbReq->m_DstId;
    MkString SubjectSource = pGbReq->m_SubjectSource;
    return PlayStream(DeviceId, pGbReq->m_DstId, CMkTime(Sdp.GetTime().GetStartTime(), 0), CMkTime(Sdp.GetTime().GetEndTime(), 0), Sdp.GetSessionName(), [this, Cb, ChannelId, SubjectSource, InviteSession, OfferSdp](Uint32 ErrorCode, const Json::Value &ResBody) {
        if (NoneError != ErrorCode) {
            Cb(ErrorCode, nullptr);
            return;
        }
        MkString MediaServerId = ResBody["MediaServerID"].asString();
        MkString MediaPath = ResBody["MediaPath"].asString();
        MkString Subject = SubjectSource + "," + MediaServerId + ":" + std::to_string(CMkUtil::GetRandomNumber());
        ErrorCode = m_pGb28181->InviteRequest(MediaServerId, ChannelId, Subject, OfferSdp, [this, InviteSession, Cb](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {
            const CMkGbInviteResponse* pInviteRes = dynamic_cast<const CMkGbInviteResponse*>(pGbRes);
            if (NoneError == ErrorCode && pInviteRes) {
                m_UpPlayLock.WLock();
                m_MapUpPlay[InviteSession] = pInviteRes->m_SessionId;
                m_UpPlayLock.WUnlock();
            }
            Cb(ErrorCode, pGbRes);
            if (pInviteRes) {
                pInviteRes->m_EventResCb(MkMapString(), "");
            }
        });
        if (NoneError != ErrorCode) {
            Cb(ErrorCode, nullptr);
        }
    });
}

Uint32 CMkGbServer::OnGbByeRequest(const CMkGbByeReqeust* pGbReq, const MkGbResponseCallback& Cb)
{
    if (!pGbReq) {
        return InvalidParams;
    }
    Cb(NoneError, nullptr);
    MkString RemoteSession;
    m_UpPlayLock.WLock();
    MkMapString::iterator it = m_MapUpPlay.begin();
    for (; it != m_MapUpPlay.end(); it++) {
        if (pGbReq->m_SessionId == it->first) {
            RemoteSession = it->second;
            m_MapUpPlay.erase(it);
            break;
        } else if (pGbReq->m_SessionId == it->second) {
            RemoteSession = it->first;
            m_MapUpPlay.erase(it);
            break;
        }
    }
    m_UpPlayLock.WUnlock();
    if (!RemoteSession.empty()) {
        m_pGb28181->ByeRequest(RemoteSession, nullptr);
        return NoneError;
    }
    RemoteSession.clear();
    m_PlayLock.WLock();
    MkMap<MkString, MkGbPlayParam>::iterator itPlay = m_MapPlay.begin();
    for (; itPlay != m_MapPlay.end(); itPlay++) {
        if (pGbReq->m_SessionId == itPlay->second.ToChannelSession) {
            RemoteSession = itPlay->second.ToMediaServerSession;
            m_MapPlay.erase(itPlay);
            break;
        } else if (pGbReq->m_SessionId == itPlay->second.ToMediaServerSession) {
            RemoteSession = itPlay->second.ToChannelSession;
            m_MapPlay.erase(itPlay);
            break;
        }
    }
    m_PlayLock.WUnlock();
    if (!RemoteSession.empty()) {
        m_pGb28181->ByeRequest(RemoteSession, nullptr);
        return NoneError;
    }

    RemoteSession.clear();
    m_DecoderLock.WLock();
    MkMap<MkString, MkGbDecoderParam>::iterator itDecoder = m_MapDecoder.begin();
    for (; itDecoder != m_MapDecoder.end(); itDecoder++) {
        if (pGbReq->m_SessionId == itDecoder->second.ToDecoderSession) {
            RemoteSession = itDecoder->second.ToMediaServerSession;
            m_MapDecoder.erase(itDecoder);
            break;
        } else if (pGbReq->m_SessionId == itDecoder->second.ToMediaServerSession) {
            RemoteSession = itDecoder->second.ToMediaServerSession;
            m_MapDecoder.erase(itDecoder);
            break;
        }
    }
    m_DecoderLock.WUnlock();
    if (!RemoteSession.empty()) {
        m_pGb28181->ByeRequest(RemoteSession, nullptr);
    }
    return NoneError;
}

Uint32 CMkGbServer::OnGbDeviceKeepAlive(const CMkGbMessageRequest* pGbReq, const MkGbResponseCallback& Cb)
{
    Uint32 ErrorCode = InvalidParams;
    m_OnlineDeviceLock.RLock();
    MkMap<MkString, MkOnlineDevice>::iterator it = m_MapOnlineDevice.find(pGbReq->m_DeviceId);
    if (it != m_MapOnlineDevice.end()) {
        it->second.LastKeepAliveTime = NowMkTime;
        ErrorCode = NoneError;
    }
    m_OnlineDeviceLock.RUnlock();
    Cb(ErrorCode, nullptr);
    return NoneError;
}

Uint32 CMkGbServer::OnDeviceCheckTimer()
{
    CMkTime NowTime = NowMkTime;
    MkVector<MkString> VecOfflineDevice;
    m_OnlineDeviceLock.RLock();
    MkMap<MkString, MkOnlineDevice>::iterator it = m_MapOnlineDevice.begin();
    for (; it != m_MapOnlineDevice.end(); it++) {
        if (NowTime.OffsetSec(it->second.LastKeepAliveTime) > (int)(it->second.HBCount*it->second.HBInterval)) {
            VecOfflineDevice.push_back(it->first);
        }
    }
    m_OnlineDeviceLock.RUnlock();
    MkVector<MkString>::iterator itVec = VecOfflineDevice.begin();
    for (; itVec != VecOfflineDevice.end(); itVec++) {
        DeleteOnlineDevice(*itVec);
    }
    return NoneError;
}

Uint32 CMkGbServer::OnRequestJsonParse(const MkHttpMethod& Method, const MkString& Path, const MkMap<MkString, MkString>& MapQuery, const Json::Value& JsonReq, const MkHttpResponseJsonCb& cb)
{
    Uint32 ErrorCode = NoneError;
    MapParser TmpMapParser;
    switch (Method) {
    case MkHttpMethodDelete:
        TmpMapParser = m_MapDeleteParser;
        break;
    case MkHttpMethodGet:
        TmpMapParser = m_MapGetParser;
        break;
    case MkHttpMethodPut:
        TmpMapParser = m_MapPutParser;
        break;
    case MkHttpMethodPost:
        TmpMapParser = m_MapPostParser;
        break;
    default:
        ErrorCode = UnSupported;
        break;
    }
    MapParser::iterator it = TmpMapParser.find(Path);
    if (it != TmpMapParser.end()) {
        ErrorCode = (this->*(it->second))(JsonReq, MapQuery, cb);
    } else {
        Json::Value Support;
        it = TmpMapParser.begin();
        for (int i = 0; it != TmpMapParser.end(); it++, i++) {
            Support[i] = GetApiUriPrefix() + it->first;
        }
        cb(InvalidUrl, Support);
        return NoneError;
    }
    return ErrorCode;
}

Uint32 CMkGbServer::OnWebSockekAccessed(CMkHttpSession* pSession)
{
    Json::Value JsonNotify;
    Json::Value JsonData;
    MkString strNotify;
    //notify all device

    MkMap<MkString, MkOnlineDevice> MapDevice;
    m_OnlineDeviceLock.RLock();
    MapDevice = m_MapOnlineDevice;
    m_OnlineDeviceLock.RUnlock();

    MkMap<MkString, MkOnlineDevice>::iterator it = MapDevice.begin();
    for (int i = 0; it != MapDevice.end(); it++, i++) {
        NotifyDeviceOnline(it->second.DeviceId, TRUE, pSession);
        //NotifyCatalog(it->second.DeviceId, it->second.VecCatalog, WsSessionId);
    }
    return NoneError;
}

Uint32 CMkGbServer::GetVersionParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb)
{
    MkUnUse(JsonReq);
    MkUnUse(MapQuery);

    MkString Version;
    GetVersion(Version);
    Json::Value ResBody;
    ResBody["version"] = Version;
    ResCb(NoneError, ResBody);
    return NoneError;
}

Uint32 CMkGbServer::GetWebSocketAccessKeyParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb)
{
    MkUnUse(JsonReq);
    MkUnUse(MapQuery);

    Json::Value ResBody;
    ResBody["key"] = GetWebSocketAccessKey();
    ResCb(NoneError, ResBody);
    return NoneError;
}

Uint32 CMkGbServer::GetConfigParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb)
{
    MkUnUse(JsonReq);
    MkUnUse(MapQuery);
    Json::Value ResBody;
    MkVectorString VecAppNames;
    m_ConfigIni.GetProfileAppNames(VecAppNames);
    MkVectorString::iterator it = VecAppNames.begin();
    for (; it != VecAppNames.end(); it++) {
        MkVectorString VecKeyNames;
        m_ConfigIni.GetProfileKeyNames(*it, VecKeyNames);
        MkVectorString::iterator itKey = VecKeyNames.begin();
        for (; itKey != VecKeyNames.end(); itKey++) {
            ResBody[*it + "." + *itKey] = m_ConfigIni.GetProfileString(*it, *itKey, "");
        }
    }
    ResCb(NoneError, ResBody);
    return NoneError;
}

Uint32 CMkGbServer::ChangeConfigParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb)
{
    //Uint32 ErrorCode = NoneError;
    //Uint16 HttpPort = JsonReq["httpPort"].asInt();
    //MkString HttpHost = JsonReq["httpHost"].asString();
    //MkString ServerId = JsonReq["serverId"].asString();
    //MkString GbRealm = JsonReq["gbRealm"].asString();
    //MkString GbListenHost = JsonReq["gbListenHost"].asString();
    //Uint16 GbListenPort = JsonReq["gbListenPort"].asInt();
    //MkString GbMappingHost = JsonReq["gbMappingHost"].asString();
    //Uint16 GbMappingPort = JsonReq["gbMappingPort"].asInt();
    //if (m_ServerId != ServerId
    //    || m_GbRealm != GbRealm
    //    || m_GbListenHost != GbListenHost
    //    || m_GbListenPort != GbListenPort
    //    || m_GbMappingHost != GbMappingHost
    //    || m_GbMappingPort != GbMappingPort) {
    //    m_pGb28181->Stop();

    //    MkGbStartParam Param;
    //    Param.LocalHost = GbListenHost;
    //    Param.LocalPort = GbListenPort;
    //    Param.SipId = ServerId;
    //    Param.SipRealm = GbRealm;
    //    Param.MappingHost = GbMappingHost;
    //    Param.MappingPort = GbListenPort;
    //    Param.RegisterExpires = 3600;
    //    Param.SubscribeExpires = 3600;
    //    ErrorCode = m_pGb28181->Start(Param, [this](const CMkGbRequest *pRequest, const MkGbResponseCallback& Cb) {
    //        return OnGbRequest(pRequest, Cb);
    //    });
    //    MkCheckErrorLog(ErrorCode, "start gb failed\n");
    //}

    //m_ServerId = ServerId;
    //m_GbRealm = GbRealm;
    //m_GbListenHost = GbListenHost;
    //m_GbListenPort = GbListenPort;
    //m_GbMappingHost = GbMappingHost;
    //m_GbMappingPort = GbMappingPort;
    //if (!HttpHost.empty()
    //    && (HttpHost != m_HttpHost
    //        || HttpPort != m_HttpPort)) {
    //    ErrorCode = CMkUtil::CheckTcpIsUseAbled(HttpPort, HttpHost);
    //    MkCheckErrorLog(ErrorCode, "port:%d host:%s tcp check failed\n", HttpHost.c_str(), HttpPort);
    //    m_HttpHost = HttpHost;
    //    m_HttpPort = HttpPort;
    //    ResCb(NoneError, Json::Value());
    //    WriteConfig();
    //    GetTimer()->LoopBreak();
    //    return NoneError;
    //}
    //WriteConfig();
    ResCb(NoneError, Json::Value());
    return NoneError;
}

Uint32 CMkGbServer::GetHttpHookerParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb)
{
    MkUnUse(JsonReq);
    MkUnUse(MapQuery);
    Json::Value ResBody;
    ResBody["userName"] = m_pHttpHooker->GetUserName();
    ResBody["password"] = m_pHttpHooker->GetPassword();
    ResBody["httpUrl"] = m_pHttpHooker->GetHttpUrl();
    Json::Value JsonParam;
    PacketMapParamToJson(m_pHttpHooker->GetUriParam(), JsonParam);
    if (!JsonParam.empty()) {
        ResBody["uriParam"] = JsonParam;
    }
    ResCb(NoneError, ResBody);
    return NoneError;
}

Uint32 CMkGbServer::ChangeHttpHookerParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb)
{
    m_pHttpHooker->SetUserPass(JsonReq["userName"].asString(), JsonReq["password"].asString());
    m_pHttpHooker->SetHttpUrl(JsonReq["httpUrl"].asString());
    Json::Value JsonParam = JsonReq["uriParam"];
    Json::Value::Members member = JsonParam.getMemberNames();
    Json::Value::Members::iterator iter = member.begin();
    for (; iter != member.end(); iter++) {
        m_pHttpHooker->AddUriParam(*iter, JsonParam[*iter].asString());
    }
    return NoneError;
}

Uint32 CMkGbServer::GetOnlineDeviceParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb)
{
    MkString DeviceId = GetRequestStringValue(JsonReq, MapQuery, "DeviceID");
    Uint32 ErrorCode = InvalidId;
    Json::Value ResBody;
    if (StringAll != DeviceId) {
        m_OnlineDeviceLock.RLock();
        MkMap<MkString, MkOnlineDevice>::iterator it = m_MapOnlineDevice.find(DeviceId);
        if (it != m_MapOnlineDevice.end()) {
            ResBody[0]["DeviceID"] = it->second.DeviceId;
            ResBody[0]["deviceHost"] = it->second.DevHost;
            ResBody[0]["devicePort"] = it->second.DevPort;
            ErrorCode = NoneError;
        }
        m_OnlineDeviceLock.RUnlock();
    } else {
        m_OnlineDeviceLock.RLock();
        MkMap<MkString, MkOnlineDevice>::iterator it = m_MapOnlineDevice.begin();
        for (int i = 0; it != m_MapOnlineDevice.end(); it++, i++) {
            ResBody[i]["DeviceID"] = it->second.DeviceId;
            ResBody[i]["deviceHost"] = it->second.DevHost;
            ResBody[i]["devicePort"] = it->second.DevPort;
            ErrorCode = NoneError;
        }
        m_OnlineDeviceLock.RUnlock();
        ErrorCode = NoneError;
    }
    MkCheckErrorLog(ErrorCode, "input id:%s invalid\n", DeviceId.c_str());
    ResCb(NoneError, ResBody);
    return NoneError;
}

Uint32 CMkGbServer::StartPlayParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb)
{
    MkString ChannelId = GetRequestStringValue(JsonReq, MapQuery, "ChannelID");
    MkString DeviceId = GetRequestStringValue(JsonReq, MapQuery, "DeviceID");
    MkString BeginTime = GetRequestStringValue(JsonReq, MapQuery, "BeginTime");
    MkString EndTime = GetRequestStringValue(JsonReq, MapQuery, "EndTime");
    MkString PlayType = GetRequestStringValue(JsonReq, MapQuery, "PlayType");
    Uint32 ErrorCode = NoneError;
    if (DeviceId.empty()) {
        ErrorCode = GetDevice(ChannelId, DeviceId);
        MkCheckErrorLog(ErrorCode, "input invalid channel id:%s\n", ChannelId.c_str());
    }

    if (ChannelId.empty()
        || DeviceId.empty()) {
        return InvalidParams;
    }
    if ("Play" != PlayType
        && "Playback" != PlayType) {
        return InvalidParams;
    }

    return PlayStream(DeviceId, ChannelId, BeginTime, EndTime, PlayType, ResCb);
}


Uint32 CMkGbServer::StopPlayParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb)
{
    MkString MediaPath = GetRequestStringValue(JsonReq, MapQuery, "MediaPath");
    MkGbPlayParam Param;
    Uint32 ErrorCode = GetPlayInfo(MediaPath, Param);
    if (NoneError == ErrorCode) {
        m_pGb28181->ByeRequest(Param.ToChannelSession, nullptr);
        m_pGb28181->ByeRequest(Param.ToMediaServerSession, nullptr);
        DeletePlay(MediaPath);
    }
    ResCb(ErrorCode, Json::Value());
    return NoneError;
}

Uint32 CMkGbServer::PlayControlParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb)
{
    MkString Session = GetRequestStringValue(JsonReq, MapQuery, "Session");
    MkString ControlCmd = GetRequestStringValue(JsonReq, MapQuery, "ControlCmd");
    float fSpeed = GetRequestFloatValue(JsonReq, MapQuery, "Speed");
    Uint32 OffsetSec = GetRequestUint32Value(JsonReq, MapQuery, "OffsetSecond");

    MkGbPlayControlType ControlType;
    MkUnorderedMap<MkString, MkGbPlayControlType>::iterator it = m_MapPlayControl.find(ControlCmd);
    if (it != m_MapPlayControl.end()) {
        ControlType = it->second;
    } else {
        return InvalidParams;
    }
    return m_pGb28181->InviteInfoRequest(Session, ControlType, fSpeed, OffsetSec, [this, ResCb](Uint32 ErrorCode, const CMkGbResponse* pRes) {
        ResCb(ErrorCode, Json::Value());
    });
}

Uint32 CMkGbServer::StartDecodeParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb)
{
    MkString MediaPath = GetRequestStringValue(JsonReq, MapQuery, "MediaPath");
    MkString MediaServerId = GetRequestStringValue(JsonReq, MapQuery, "MediaServerID");
    MkString DecoderChannelId = GetRequestStringValue(JsonReq, MapQuery, "DecoderChannelID");
    MkString DecoderDeviceId = GetRequestStringValue(JsonReq, MapQuery, "DecoderDeviceID");
    Uint32 ErrorCode = NoneError;
    if (DecoderDeviceId.empty()) {
        ErrorCode = GetDevice(DecoderChannelId, DecoderDeviceId);
        MkCheckErrorLog(ErrorCode, "input invalid decoder channel id:%s\n", DecoderChannelId.c_str());
    }

    //invite to decoder first
    return m_pGb28181->InviteRequest(DecoderDeviceId, DecoderChannelId, "", "", [this, ResCb, MediaPath, MediaServerId, DecoderDeviceId, DecoderChannelId](Uint32 ErrorCode, const CMkGbResponse* pResponse) {
        const CMkGbInviteResponse *pRes = dynamic_cast<const CMkGbInviteResponse*>(pResponse);
        if (!pRes) {
            ResCb(SystemError, Json::Value());
            return;
        }
        MkString OfferSdp = pRes->m_AnwserSdp;
        EventResponseCallback EventCb = pRes->m_EventResCb;
        MkString DecoderSession = pRes->m_SessionId;
        ErrorCode = m_pGb28181->InviteRequest(MediaServerId, MediaPath, "", OfferSdp, [this, EventCb, ResCb, MediaPath, MediaServerId, DecoderSession, DecoderDeviceId, DecoderChannelId](Uint32 ErrorCode, const CMkGbResponse* pResponse) {
            const CMkGbInviteResponse *pRes = dynamic_cast<const CMkGbInviteResponse*>(pResponse);
            if (!pRes) {
                return;
            }
            pRes->m_EventResCb(MkMapString(), "");
            EventCb(MkMapString(), pRes->m_AnwserSdp);
            if (NoneError != ErrorCode) {
                ResCb(SystemError, Json::Value());
                m_pGb28181->ByeRequest(DecoderSession, nullptr);
                return;
            }
            m_DecoderLock.WLock();
            MkGbDecoderParam Param;
            Param.DecoderChannelId = DecoderChannelId;
            Param.DecoderDeviceId = DecoderDeviceId;
            Param.MediaPath = MediaPath;
            Param.MediaServerId = MediaServerId;
            Param.ToDecoderSession = DecoderSession;
            Param.ToMediaServerSession = pRes->m_SessionId;
            m_MapDecoder[DecoderSession] = Param;
            m_DecoderLock.WUnlock();
            Json::Value ResBody;
            ResBody["Session"] = DecoderSession;
            ResCb(NoneError, ResBody);
        });
        if (NoneError != ErrorCode) {
            ResCb(ErrorCode, Json::Value());
        }
    });
}

Uint32 CMkGbServer::StopDecodeParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb)
{
    MkString Session = GetRequestStringValue(JsonReq, MapQuery, "Session");
    MkString RemoteSession;
    m_DecoderLock.WLock();
    MkMap<MkString, MkGbDecoderParam>::iterator it = m_MapDecoder.find(Session);
    if (it != m_MapDecoder.end()) {
        RemoteSession = it->second.ToMediaServerSession;
        m_MapDecoder.erase(it);
    }
    m_DecoderLock.WUnlock();

    if (!RemoteSession.empty()) {
        m_pGb28181->ByeRequest(Session, nullptr);
        m_pGb28181->ByeRequest(RemoteSession, nullptr);
    }

    return NoneError;
}

Uint32 CMkGbServer::DeviceQueryParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb)
{
    MkString RouterId = GetRequestStringValue(JsonReq, MapQuery, "RouterID");
    MkString DstId = GetRequestStringValue(JsonReq, MapQuery, "DestinationID");
    MkString CmdType = GetRequestStringValue(JsonReq, MapQuery, "CmdType");
    if (RouterId.empty() || CmdType.empty() || DstId.empty()) {
        MkErrorLog("input param:%s invalid\n", JsonReq.toStyledString().c_str());
        return InvalidParams;
    }
    CMkGbMessageRequest Req;
    Req.m_DstId = DstId;
    Req.m_RouterId = RouterId;
    Req.m_DeviceId = DstId;
    Req.m_CmdType = CmdType;
    Req.m_MessageType = "Query";
    ParseJsonContentToGbMessage(JsonReq["Param"], Req.m_Message);
    return m_pGb28181->MessageRequest(Req, [this, ResCb, RouterId, DstId, CmdType](Uint32 ErrorCode, const CMkGbResponse* pRes) {
        const CMkGbMessageResponse *pMsgRes = dynamic_cast<const CMkGbMessageResponse*>(pRes);
        if (!pMsgRes) {
            ResponseHttp(ResCb, SystemError, nullptr);
            return;
        }
        if (pMsgRes->m_SumNum <= pMsgRes->m_Message.VecChildren.size()) {
            ResponseHttp(ResCb, ErrorCode, pMsgRes);
        } else {
            MkString strKey = RouterId + DstId + CmdType;
            CMkGbMessageResponse TmpResponse = *pMsgRes;
            BOOL bResHttp = FALSE;
            m_QueryLock.Lock();
            MkMap<MkString, MkVector<MkGbMessage>>::iterator it = m_QueryResult.find(strKey);
            if (it != m_QueryResult.end()) {
                it->second.insert(it->second.end(), pMsgRes->m_Message.VecChildren.begin(), pMsgRes->m_Message.VecChildren.end());
                if (it->second.size() >= pMsgRes->m_SumNum) {
                    TmpResponse.m_Message.VecChildren = it->second;
                    bResHttp = TRUE;
                    m_QueryResult.erase(it);
                }
            } else {
                m_QueryResult[strKey] = pMsgRes->m_Message.VecChildren;
            }
            m_QueryLock.Unlock();
            if (bResHttp) {
                ResponseHttp(ResCb, ErrorCode, &TmpResponse);
            }
        }
    });
}

Uint32 CMkGbServer::DeviceConfigParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb)
{
    MkString RouterId = GetRequestStringValue(JsonReq, MapQuery, "RouterID");
    MkString DstId = GetRequestStringValue(JsonReq, MapQuery, "DestinationID");
    if (RouterId.empty() || DstId.empty()) {
        MkErrorLog("input param:%s invalid\n", JsonReq.toStyledString().c_str());
        return InvalidParams;
    }
    CMkGbMessageRequest Req;
    Req.m_DstId = DstId;
    Req.m_RouterId = RouterId;
    Req.m_DeviceId = DstId;
    Req.m_CmdType = "DeviceConfig";
    Req.m_MessageType = "Control";
    ParseJsonContentToGbMessage(JsonReq["Param"], Req.m_Message);
    return m_pGb28181->MessageRequest(Req, [this, ResCb](Uint32 ErrorCode, const CMkGbResponse* pRes) {
        ResponseHttp(ResCb, ErrorCode, pRes);
    });
}

Uint32 CMkGbServer::DeviceControlParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb)
{
    MkString RouterId = GetRequestStringValue(JsonReq, MapQuery, "RouterID");
    MkString DstId = GetRequestStringValue(JsonReq, MapQuery, "DestinationID");
    if (RouterId.empty() || DstId.empty()) {
        MkErrorLog("input param:%s invalid\n", JsonReq.toStyledString().c_str());
        return InvalidParams;
    }
    CMkGbMessageRequest Req;
    Req.m_DstId = DstId;
    Req.m_RouterId = RouterId;
    Req.m_DeviceId = DstId;
    Req.m_CmdType = "DeviceControl";
    Req.m_MessageType = "Control";
    Uint32 ErrorCode = ParseJsonContentToGbMessage(JsonReq["Param"], Req.m_Message);
    MkCheckErrorLog(ErrorCode, "input request:%s invalid\n", JsonReq.toStyledString().c_str());
    return m_pGb28181->MessageRequest(Req, [this, ResCb](Uint32 ErrorCode, const CMkGbResponse* pRes) {
        ResponseHttp(ResCb, ErrorCode, pRes);
    });
}

Uint32 CMkGbServer::CatalogChangeParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb)
{
    MkString UpServerId = GetRequestStringValue(JsonReq, MapQuery, "ServerID");
    Json::Value Param = JsonReq["Param"];
    if (UpServerId.empty() || Param.empty()) {
        return InvalidParams;
    }

    MkString CatalogSubscribeId;
    m_GbServerLock.RLock();
    MkMap<MkString, MkUpGbServer>::iterator it = m_MapUpGbServer.find(UpServerId);
    if (it != m_MapUpGbServer.end()) {
        CatalogSubscribeId = it->second.CatalogSubscribeId;
    }
    m_GbServerLock.RUnlock();
    if (CatalogSubscribeId.empty()) {
        return InvalidParams;
    }
    CMkGbNotifyRequest Req;
    Req.m_State = "active";
    Req.m_SubscribeId = CatalogSubscribeId;
    Req.m_CmdType = "Catalog";
    Req.m_MessageType = "Notify";
    ParseJsonContentToGbMessage(Param, Req.m_Message);
    return m_pGb28181->NotifyRequest(Req, [this, ResCb](Uint32 ErrorCode, const CMkGbResponse* pRes) {
        ResCb(ErrorCode, Json::Value());
    });
}


Uint32 CMkGbServer::AddUpServerParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb)
{
    MkUpGbServer Svr;
    Svr.GbSvrId = GetRequestStringValue(JsonReq, MapQuery, "ServerID");
    Svr.GbSvrRealm = GetRequestStringValue(JsonReq, MapQuery, "ServerRealm");
    Svr.GbSvrHost = GetRequestStringValue(JsonReq, MapQuery, "ServerHost");
    Svr.GbSvrPort = GetRequestUint32Value(JsonReq, MapQuery, "ServerPort");
    Svr.HBInterval = GetRequestUint32Value(JsonReq, MapQuery, "HeatBeatInterval");
    Svr.HBCount = GetRequestUint32Value(JsonReq, MapQuery, "HeatBeatCount");
    Svr.Expires = GetRequestUint32Value(JsonReq, MapQuery, "Expires");
    Svr.bTcp = GetRequestBoolValue(JsonReq, MapQuery, "TcpSip");
    Uint32 ErrorCode = IdIsUsed;
    m_GbServerLock.WLock();
    MkMap<MkString, MkUpGbServer>::iterator it = m_MapUpGbServer.find(Svr.GbSvrId);
    if (it == m_MapUpGbServer.end()) {
        ErrorCode = NoneError;
        m_MapUpGbServer[Svr.GbSvrId] = Svr;
    }
    m_GbServerLock.WUnlock();
    MkCheckErrorLog(ErrorCode, "input gb id:%s is used\n", Svr.GbSvrId.c_str());
    ResCb(NoneError, Json::Value()); //response add success
    WriteUpSvrJson();
    m_pGb28181->AddRouter(Svr.GbSvrId, Svr.GbSvrRealm, Svr.GbSvrHost, Svr.GbSvrPort, Svr.bTcp);
    CMkGbDeviceAuthorRequest Req;
    Req.m_RouterId = Svr.GbSvrId;
    Req.m_DstId = Svr.GbSvrId;
    Req.m_Realm = Svr.GbSvrRealm;
    Req.m_Expires = Svr.Expires;
    return RegisterUpServer(Req);
}

Uint32 CMkGbServer::GetUpServerParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb)
{
    MkString ServerId = GetRequestStringValue(JsonReq, MapQuery, "ServerID");
    if (ServerId.empty()) {
        return InvalidParams;
    }
    Json::Value JsonUpSvr;
    m_GbServerLock.RLock();
    if (StringAll == ServerId) {
        MkMap<MkString, MkUpGbServer>::iterator it = m_MapUpGbServer.begin();
        for (int i = 0; it != m_MapUpGbServer.end(); it++, i++) {
            JsonUpSvr[i]["ServerId"] = it->second.GbSvrId;
            JsonUpSvr[i]["ServerRealm"] = it->second.GbSvrRealm;
            JsonUpSvr[i]["ServerHost"] = it->second.GbSvrHost;
            JsonUpSvr[i]["ServerPort"] = it->second.GbSvrPort;
            JsonUpSvr[i]["HBInterval"] = it->second.HBInterval;
            JsonUpSvr[i]["HBCount"] = it->second.HBCount;
            JsonUpSvr[i]["Expires"] = it->second.Expires;
            JsonUpSvr[i]["TcpSip"] = it->second.bTcp;
            JsonUpSvr[i]["Online"] = it->second.bOnline;
        }
    } else {
        MkMap<MkString, MkUpGbServer>::iterator it = m_MapUpGbServer.find(ServerId);
        if (it != m_MapUpGbServer.end()) {
            JsonUpSvr["ServerId"] = it->second.GbSvrId;
            JsonUpSvr["ServerRealm"] = it->second.GbSvrRealm;
            JsonUpSvr["ServerHost"] = it->second.GbSvrHost;
            JsonUpSvr["ServerPort"] = it->second.GbSvrPort;
            JsonUpSvr["HBInterval"] = it->second.HBInterval;
            JsonUpSvr["HBCount"] = it->second.HBCount;
            JsonUpSvr["Expires"] = it->second.Expires;
            JsonUpSvr["TcpSip"] = it->second.bTcp;
            JsonUpSvr["Online"] = it->second.bOnline;
        }
    }
    m_GbServerLock.RUnlock();
    ResCb(NoneError, JsonUpSvr);
    return NoneError;
}

Uint32 CMkGbServer::DeleteUpServerParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb)
{
    MkString GbSvrId = GetRequestStringValue(JsonReq, MapQuery, "ServerID");
    BOOL bFind = FALSE;
    MkUpGbServer GbSvr;
    m_GbServerLock.RLock();
    MkMap<MkString, MkUpGbServer>::iterator it = m_MapUpGbServer.find(GbSvrId);
    if (it != m_MapUpGbServer.end()) {
        GbSvr = it->second;
        bFind = TRUE;
    }
    m_GbServerLock.RUnlock();

    if (bFind) {
        //TODO invite bye

        GetTimer()->DeleteTimer(GbSvr.KeepAliverTimer);
        GetTimer()->DeleteDelayer(GbSvr.RegisterDelayer);
        CMkGbDeviceAuthorRequest Req;
        Req.m_RouterId = GbSvrId;
        Req.m_Expires = 0;
        Req.m_DstId = GbSvrId;
        Req.m_Realm = GbSvr.GbSvrRealm;
        RegisterUpServer(Req, TRUE);
    }
    ResCb(NoneError, Json::Value());
    return NoneError;
}

Uint32 CMkGbServer::DefaultCallbackParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb)
{
    MkString Action = GetRequestStringValue(JsonReq, MapQuery, "action");
    Json::Value JsonData = JsonReq["data"];
    Json::Value ResBody;
    Uint32 ErrorCode = NoneError;
    if ("DeviceAuthor" == Action) {
        MkDebugLog("recv device author");
        ResBody["Redirect"] = false;
        //ResBody["RedirectHost"] = "192.168.100.120";
        //ResBody["RedirectPort"] = 5060;
        //ResBody["RedirectID"] = "34020000002001000000";
        ErrorCode = NoneError;
    } else if ("Catalog" == Action) {
        MkDebugLog("recv catalog request\n");
        Uint32 nIndex = 0;
        Json::Value JsonDevList;
        //m_OnlineDeviceLock.RLock();
        //MkMap<MkString, MkOnlineDevice>::iterator it = m_MapOnlineDevice.begin();
        //for (; it != m_MapOnlineDevice.end(); it++) {
        //    MkVector<MkMapString>::iterator itVec = it->second.VecCatalog.begin();
        //    for (; itVec != it->second.VecCatalog.end(); itVec++) {
        //        PacketMapParamToJson(*itVec, JsonDevList[nIndex]);
        //        JsonDevList[nIndex]["Parental"] = "1";
        //        JsonDevList[nIndex]["ParentID"] = m_pGb28181->GetSipId();
        //        nIndex++;
        //    }
        //}
        //m_OnlineDeviceLock.RUnlock();
        JsonDevList[nIndex]["Address"] = "Address";
        JsonDevList[nIndex]["CivilCode"] = m_pGb28181->GetRealm();
        JsonDevList[nIndex]["DeviceID"] = m_pGb28181->GetSipId();
        JsonDevList[nIndex]["Manufacturer"] = "mk gb server";
        JsonDevList[nIndex]["Model"] = "Model";
        JsonDevList[nIndex]["Name"] = "mk gb server";
        JsonDevList[nIndex]["Owner"] = "mk";
        JsonDevList[nIndex]["ParentID"] = m_pGb28181->GetSipId();
        JsonDevList[nIndex]["Parental"] = "1";
        JsonDevList[nIndex]["RegisterWay"] = "1";
        JsonDevList[nIndex]["SafetyWay"] = "1";
        JsonDevList[nIndex]["Secrecy"] = "0";
        JsonDevList[nIndex]["Status"] = "ON";
        nIndex++;
        ResBody["DeviceList"] = JsonDevList;
        ResBody["SunNum"] = nIndex;
    } else if ("ServerRegister" == Action) {
        MkDebugLog("recv server register request\n");
        MkString UserName = JsonReq["ServerId"].asString();
        MkString Password = "admin";
        MkString Uri = JsonReq["Uri"].asString();
        MkString Nonce = JsonReq["Nonce"].asString();
        MkString Algorithm = JsonReq["Algorithm"].asString();
        MkString Realm = JsonReq["Realm"].asString();
        if ("MD5" == Algorithm) {
            MkString Ha1 = CMkMd5Encode::Encode(UserName + ":" + Realm + ":" + Password);
            MkString Ha2 = CMkMd5Encode::Encode("REGISTER:" + Uri);
            MkString Ha3 = CMkMd5Encode::Encode(Ha1 + ":" + Nonce + ":" + Ha2);
            ResBody["UserName"] = UserName;
            ResBody["Response"] = Ha3;
        } else {
            ErrorCode = InvalidParams;
        }
    }
    ResCb(ErrorCode, ResBody);
    return NoneError;
}

Uint32 CMkGbServer::NotifyMsg(const MkNotifyMessageType& ActionType, const Json::Value& Body, CMkHttpSession* pSession/* = nullptr*/)
{
    MkString Action;
    Uint32 ErrorCode = GetNotifyAction(ActionType, Action);
    MkCheckErrorLog(ErrorCode, "invalid action type:%d\n", ActionType);
    Json::Value JsonNotify;
    JsonNotify["Action"] = Action;
    JsonNotify["ServerId"] = m_ConfigIni.GetProfileString(GbServerId);
    if (!Body.empty()) {
        JsonNotify["data"] = Body;
    }
    if (!pSession) {
        BroadCastMsg(JsonNotify.toStyledString());
    } else {
        pSession->SendWebSocketText(JsonNotify.toStyledString());
    }
    return NoneError;
}

Uint32 CMkGbServer::NotifyMsg(const MkString& strAction, const Json::Value& Body, CMkHttpSession* pSession/* = nullptr*/)
{
    Json::Value JsonNotify;
    JsonNotify["Action"] = strAction;
    JsonNotify["ServerID"] = m_ConfigIni.GetProfileString(GbServerId);
    if (!Body.empty()) {
        JsonNotify["data"] = Body;
    }
    if (!pSession) {
        BroadCastMsg(JsonNotify.toStyledString());
    } else {
        pSession->SendWebSocketText(JsonNotify.toStyledString());
    }
    return NoneError;
}

Uint32 CMkGbServer::NotifyCatalog(const MkString& DeviceId, const MkVector<MkMapString>& VecCatalog, CMkHttpSession* pSession/* = nullptr*/)
{
    Json::Value JsonCatalog;
    MkVector<MkMapString>::const_iterator itCatalog = VecCatalog.begin();
    for (int i = 0; itCatalog != VecCatalog.end(); itCatalog++, i++) {
        PacketMapParamToJson(*itCatalog, JsonCatalog[i]);
    }
    Json::Value JsonBody;
    JsonBody["DeviceID"] = DeviceId;
    JsonBody["Catalog"] = JsonCatalog;
    return NotifyMsg(MkNotifyActionCatalog, JsonBody, pSession);
}

Uint32 CMkGbServer::NotifyDeviceOnline(const MkString& DeviceId, BOOL bOnline, CMkHttpSession* pSession/* = nullptr*/)
{
    Json::Value JsonBody;
    JsonBody["DeviceID"] = DeviceId;
    JsonBody["Online"] = bOnline ? true : false;
    return NotifyMsg(MkNotifyActionDeviceOnline, JsonBody, pSession);
}

Uint32 CMkGbServer::NotifyUpServerOnline(const MkString& DeviceId, BOOL bOnline, CMkHttpSession* pSession/* = nullptr*/)
{
    Json::Value JsonBody;
    JsonBody["ServerId"] = DeviceId;
    JsonBody["Online"] = bOnline ? true : false;
    return NotifyMsg(MkNotifyActionDeviceOnline, JsonBody, pSession);
}

Uint32 CMkGbServer::NotifyPlayEnd(const MkString& MediaPath, CMkHttpSession* pSession/* = nullptr*/)
{
    Json::Value JsonBody;
    JsonBody["MediaPath"] = MediaPath;
    return NotifyMsg(MkNotifyActionPlayEnd, JsonBody, pSession);
}

Uint32 CMkGbServer::NotifyPlayInfo(CMkHttpSession* pSession/* = nullptr*/)
{
    Json::Value JsonBody;
    m_PlayLock.RLock();
    MkMap<MkString, MkGbPlayParam>::iterator it = m_MapPlay.begin();
    for (int i = 0; it != m_MapPlay.end(); it++, i++) {
        JsonBody[i]["MediaPath"] = it->second.MediaPath;
        JsonBody[i]["MediaServerID"] = it->second.MediaServerId;
        JsonBody[i]["IsPlaying"] = it->second.bPlaying;
    }
    m_PlayLock.RUnlock();
    return NotifyMsg(MkNotifyActionPlayInfo, JsonBody, pSession);
}

Uint32 CMkGbServer::DeviceAuthorRequest(const CMkGbDeviceAuthorRequest& Req, const MkHttpResponseJsonCb& ResCb)
{
    Json::Value JsonReq;
    JsonReq["DeviceID"] = Req.m_RouterId;
    JsonReq["DeviceHost"] = Req.m_DeviceHost;
    JsonReq["DevicePort"] = Req.m_DevicePort;
    JsonReq["AuthorType"] = Req.m_AuthorType;
    JsonReq["UserName"] = Req.m_UserName;
    JsonReq["Nonce"] = Req.m_Nonce;
    JsonReq["Uri"] = Req.m_Uri;
    JsonReq["Response"] = Req.m_Response;
    JsonReq["Algorithm"] = Req.m_Algorithm;
    JsonReq["Expires"] = Req.m_Expires;
    return m_pHttpHooker->AsyncMsg("DeviceAuthor", JsonReq, ResCb);
}

Uint32 CMkGbServer::UpServerRegisterRequest(const MkString& ServerId, const MkString& Realm, const MkString& Nonce, const MkString& Uri, const MkString& Algorithm, const MkHttpResponseJsonCb& ResCb)
{
    Json::Value Req;
    Req["ServerId"] = ServerId;
    Req["Realm"] = Realm;
    Req["Nonce"] = Nonce;
    Req["Uri"] = Uri;
    Req["Algorithm"] = Algorithm;
    return m_pHttpHooker->AsyncMsg("ServerRegister", Req, ResCb);
}

Uint32 CMkGbServer::CatalogRequest(const MkHttpResponseJsonCb& ResCb)
{
    return m_pHttpHooker->AsyncMsg("Catalog", Json::Value(), ResCb);
}

Uint32 CMkGbServer::RealplayRequest(const MkString& DeviceId, const MkString& ChannelId, const MkString& UpRtpHost, Uint16 UpRtpPort, Uint32 UpRtpSsrc, const MkHttpResponseJsonCb& ResCb)
{
    return NoneError;
}

Uint32 CMkGbServer::AddOnlineDevice(const MkString& RegisterId, const MkString& DeviceId, const MkString& DevIp, Uint16 DevPort)
{
    Uint32 ErrorCode = NoneError;
    MkOnlineDevice OnlineDev;
    OnlineDev.DevHost = DevIp;
    OnlineDev.DeviceId = DeviceId;
    OnlineDev.DevPort = DevPort;
    OnlineDev.LastKeepAliveTime = NowMkTime;
    OnlineDev.RegisterId = RegisterId;
    m_OnlineDeviceLock.WLock();
    MkMap<MkString, MkOnlineDevice>::iterator it = m_MapOnlineDevice.find(DeviceId);
    if (it != m_MapOnlineDevice.end()) {
        if (RegisterId == it->second.RegisterId) {
            ErrorCode = IdIsUsed;
        }
    } else {
        m_MapOnlineDevice[DeviceId] = OnlineDev;
    }
    m_OnlineDeviceLock.WUnlock();
    if (NoneError == ErrorCode) {
        ErrorCode = NotifyDeviceOnline(DeviceId, TRUE);
        if ("202" == DeviceId.substr(10, 3)) {
            m_MediaServerLock.WLock();
            m_MapMediaServer[DeviceId] = MaxInt32;
            m_MediaServerLock.WUnlock();
        }
    }
    return ErrorCode;
}

Uint32 CMkGbServer::UpdateMapCatalog(const MkString& DeviceId, const MkVector<MkMapString>& VecCatalog)
{
    MkVector<MkMapString>::const_iterator itCatalog = VecCatalog.begin();
    for (; itCatalog != VecCatalog.end(); itCatalog++) {
        MkMapString::const_iterator itItem = itCatalog->find("DeviceID");
        if (itItem != itCatalog->end()) {
            m_DeviceChildLock.WLock();
            m_MapDeviceChild[itItem->second] = DeviceId;
            m_DeviceChildLock.WUnlock();
            if ("132" == itItem->second.substr(10, 3)
                || "131" == itItem->second.substr(10, 3)) {
                if (m_ConfigIni.GetProfileBoolean(GbAutoPtzPosition)) {
                    //ptz position subscribe
                    CMkGbSubscribeRequest Req;
                    Req.m_DstId = itItem->second;
                    Req.m_RouterId = DeviceId;
                    Req.m_DeviceId = itItem->second;
                    Req.m_CmdType = "PTZPosition";
                    Req.m_MessageType = "Query";
                    Req.m_Expires = m_ConfigIni.GetProfileUint32(GbSubscribeExpries);
                    Req.m_Event = "presence";
                    m_pGb28181->SubscribeRequest(Req, [this](Uint32 ErrorCode, const CMkGbResponse* pRes) {
                        MkInfoLog("catalog subscribe error:%d\n", ErrorCode);
                    });

                }
                if (m_ConfigIni.GetProfileBoolean(GbAutoSubMoPos)) {
                    CMkGbSubscribeRequest Req;
                    Req.m_DstId = itItem->second;
                    Req.m_RouterId = DeviceId;
                    Req.m_DeviceId = itItem->second;
                    Req.m_CmdType = "MobilePosition";
                    Req.m_MessageType = "Query";
                    Req.m_Expires = m_ConfigIni.GetProfileUint32(GbSubscribeExpries);
                    Req.m_Event = "presence";
                    Req.m_Message.MainParam["Interval"] = std::to_string(m_ConfigIni.GetProfileUint32(GbMoPosInterval));
                    m_pGb28181->SubscribeRequest(Req, [this](Uint32 ErrorCode, const CMkGbResponse* pRes) {
                        MkInfoLog("mobile position subscribe error:%d\n", ErrorCode);
                    });
                }
            }
        }
    }

    return NotifyCatalog(DeviceId, VecCatalog);
}

Uint32 CMkGbServer::DeleteOnlineDevice(const MkString& DeviceId)
{
    Uint32 ErrorCode = InvalidId;
    m_OnlineDeviceLock.WLock();
    MkMap<MkString, MkOnlineDevice>::iterator it = m_MapOnlineDevice.find(DeviceId);
    if (it != m_MapOnlineDevice.end()) {
        m_MapOnlineDevice.erase(it);
        ErrorCode = NoneError;
    }
    m_OnlineDeviceLock.WUnlock();
    if ("202" == DeviceId.substr(10, 3)) {
        MkInfoLog("media server:%s is offline\n", DeviceId.c_str());
        m_MediaServerLock.WLock();
        MkMap<MkString, Uint32>::iterator it = m_MapMediaServer.find(DeviceId);
        if (it != m_MapMediaServer.end()) {
            m_MapMediaServer.erase(it);
        }
        m_MediaServerLock.WUnlock();
        DeletePlayFromMediaServer(DeviceId);
    }
    DeleteDeviceChildFromDevice(DeviceId);
    return NotifyDeviceOnline(DeviceId, FALSE);
}

Uint32 CMkGbServer::GetDeviceBasicConfig(const MkString& DeviceId)
{
    CMkGbMessageRequest BasicConfigReq;
    BasicConfigReq.m_CmdType = "ConfigDownload";
    BasicConfigReq.m_MessageType = "Query";
    BasicConfigReq.m_DstId = DeviceId;
    BasicConfigReq.m_DeviceId = DeviceId;
    BasicConfigReq.m_RouterId = DeviceId;
    BasicConfigReq.m_Message.MainParam["ConfigType"] = "BasicParam";
    return m_pGb28181->MessageRequest(BasicConfigReq, [this, DeviceId](Uint32 ErrorCode, const CMkGbResponse* pRes) {
        const CMkGbMessageResponse* pMsgRes = dynamic_cast<const CMkGbMessageResponse*>(pRes);
        if (NoneError == ErrorCode && pMsgRes) {
            //MkMapString::const_iterator itExpiration = pMsgRes->m_Message.MainParam.find("Expiration");
            MkMapString::const_iterator itHbInterval = pMsgRes->m_Message.MainParam.find("HeartBeatInterval");
            MkMapString::const_iterator itHbCount = pMsgRes->m_Message.MainParam.find("HeartBeatCount");
            if (itHbCount != pMsgRes->m_Message.MainParam.end()
                && itHbInterval != pMsgRes->m_Message.MainParam.end()) {
                m_OnlineDeviceLock.WLock();
                MkMap<MkString, MkOnlineDevice>::iterator it = m_MapOnlineDevice.find(DeviceId);
                if (it != m_MapOnlineDevice.end()) {
                    it->second.HBCount = std::stoi(itHbCount->second);
                    it->second.HBInterval = std::stoi(itHbInterval->second);
                }
                m_OnlineDeviceLock.WUnlock();
            }
        }
    });
}

MkString CMkGbServer::GetFreeMediaServer()
{
    MkString ServerId;
    Uint32 MaxScore = 0;
    m_MediaServerLock.RLock();
    MkMap<MkString, Uint32>::iterator it = m_MapMediaServer.begin();
    for (; it != m_MapMediaServer.end(); it++) {
        if (MaxScore < it->second) {
            ServerId = it->first;
            MaxScore = it->second;
        }
    }
    m_MediaServerLock.RUnlock();
    return ServerId;
}

Uint32 CMkGbServer::AddMapDeviceChild(const MkString& ChildId, const MkString& DeviceId)
{
    m_DeviceChildLock.WLock();
    m_MapDeviceChild.insert(std::pair<MkString, MkString>(ChildId, DeviceId));
    m_DeviceChildLock.WUnlock();
    return NoneError;
}

Uint32 CMkGbServer::GetDevice(const MkString& ChildId, MkString& DeviceId)
{
    Uint32 ErrorCode = InvalidId;
    m_DeviceChildLock.RLock();
    MkMapString::iterator it = m_MapDeviceChild.find(ChildId);
    if (it != m_MapDeviceChild.end()) {
        DeviceId = it->second;
        ErrorCode = NoneError;
    }
    m_DeviceChildLock.RUnlock();
    return ErrorCode;
}

Uint32 CMkGbServer::DeleteDeviceChildFromDevice(const MkString& DeviceId)
{
    m_DeviceChildLock.WLock();
    MkMapString::iterator it = m_MapDeviceChild.begin();
    while (it != m_MapDeviceChild.end()) {
        if (DeviceId == it->second) {
            it = m_MapDeviceChild.erase(it);
        } else {
            it++;
        }
    }
    m_DeviceChildLock.WUnlock();
    return NoneError;
}

Uint32 CMkGbServer::DeleteDeviceChild(const MkString& ChildId)
{
    Uint32 ErrorCode = InvalidId;
    m_DeviceChildLock.WLock();
    MkMapString::iterator it = m_MapDeviceChild.find(ChildId);
    if (it != m_MapDeviceChild.end()) {
        m_MapDeviceChild.erase(it);
        ErrorCode = NoneError;
    }
    m_DeviceChildLock.WUnlock();
    return ErrorCode;
}

Uint32 CMkGbServer::RegisterUpServer(const CMkGbDeviceAuthorRequest& Req, BOOL bFailEnd/* = FALSE*/)
{
    return m_pGb28181->RegisterRequest(Req, [this, Req, bFailEnd](Uint32 ErrorCode, const CMkGbResponse* pResponse) {
        const CMkGbDeviceAuthorResponse *pRes = dynamic_cast<const CMkGbDeviceAuthorResponse*>(pResponse);
        MkUpGbServer SvrInfo;
        m_GbServerLock.RLock();
        MkMap<MkString, MkUpGbServer>::iterator it = m_MapUpGbServer.find(Req.m_RouterId);
        if (it != m_MapUpGbServer.end()) {
            SvrInfo = it->second;
            if (NoneError == ErrorCode) {
                it->second.LastKeepAliveTime = NowMkTime;
                it->second.bOnline = TRUE;
            }
        }
        m_GbServerLock.RUnlock();
        if (MkSipStatusRequestTimeout + SipResponseErrorBegin == ErrorCode && 0 == Req.m_Expires) {
            m_GbServerLock.WLock();
            MkMap<MkString, MkUpGbServer>::iterator it = m_MapUpGbServer.find(Req.m_RouterId);
            if (it != m_MapUpGbServer.end()) {
                m_MapUpGbServer.erase(it);
            }
            m_GbServerLock.WUnlock();
        }
        if (MkSipStatusUnauthorized + SipResponseErrorBegin == ErrorCode && pRes) {
            MkString Uri = "sip:" + SvrInfo.GbSvrId + "@" + SvrInfo.GbSvrRealm;
            MkString Realm = pRes->m_Realm.substr(1, pRes->m_Realm.size() - 2);
            MkString Nonce = pRes->m_Nonce.substr(1, pRes->m_Nonce.size() - 2);
            CMkGbDeviceAuthorResponse AuthorRes = *pRes;
            ErrorCode = UpServerRegisterRequest(SvrInfo.GbSvrId, Realm, Nonce, Uri, pRes->m_Algorithm, [this, SvrInfo, Req, AuthorRes, Uri](Uint32 ErrorCode, const Json::Value& ResBody) {
                CMkGbDeviceAuthorRequest ReReq;
                ReReq.m_AuthorType = AuthorRes.m_AuthType;
                ReReq.m_UserName = ResBody["UserName"].asString();
                ReReq.m_Algorithm = AuthorRes.m_Algorithm;
                ReReq.m_Expires = Req.m_Expires;
                ReReq.m_Realm = AuthorRes.m_Realm;
                ReReq.m_Nonce = AuthorRes.m_Nonce;
                ReReq.m_RouterId = SvrInfo.GbSvrId;
                ReReq.m_Response = ResBody["Response"].asString();
                ReReq.m_Uri = "\"" + Uri + "\"";
                ReReq.m_DstId = SvrInfo.GbSvrId;
                //TODO Add
                RegisterUpServer(ReReq);
            });
        } else if (NoneError == ErrorCode) {
            if (0 == Req.m_Expires) {
                m_GbServerLock.WLock();
                MkMap<MkString, MkUpGbServer>::iterator it = m_MapUpGbServer.find(Req.m_RouterId);
                if (it != m_MapUpGbServer.end()) {
                    m_MapUpGbServer.erase(it);
                }
                m_GbServerLock.WUnlock();
                WriteUpSvrJson();
            } else {
                GetTimer()->AddTimer([this, SvrInfo]() {
                    NotifyKeepAliveUpServer(SvrInfo.GbSvrId);
                }, SvrInfo.HBInterval * 1000, SvrInfo.KeepAliverTimer);
            }
        } else {
            if (!bFailEnd) {
                GetTimer()->AddDelayer([this, Req]() {
                    RegisterUpServer(Req);
                }, 60 * 1000, SvrInfo.RegisterDelayer);
            }
        }
    });
}

Uint32 CMkGbServer::NotifyKeepAliveUpServer(const MkString& SvrId)
{
    CMkGbMessageRequest Req;
    Req.m_RouterId = SvrId;
    Req.m_DstId = SvrId;
    Req.m_DeviceId = m_pGb28181->GetSipId();
    Req.m_CmdType = "Keepalive";
    Req.m_MessageType = "Notify";
    return m_pGb28181->MessageRequest(Req, [this, SvrId](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {
        MkUpGbServer Svr;
        m_GbServerLock.WLock();
        MkMap<MkString, MkUpGbServer>::iterator it = m_MapUpGbServer.find(SvrId);
        if (it != m_MapUpGbServer.end()) {
            if (NoneError == ErrorCode) {
                it->second.LastKeepAliveTime = NowMkTime;
            } else if (NowMkTime - it->second.LastKeepAliveTime > (Uint64)it->second.HBCount *it->second.HBInterval * 1000 * 1000) {
                it->second.bOnline = FALSE;
                Svr = it->second;
            }
        }
        m_GbServerLock.WUnlock();
        if (!Svr.RegisterDelayer.empty()) {
            GetTimer()->AddDelayer([this, Svr]() {
                CMkGbDeviceAuthorRequest Req;
                Req.m_RouterId = Svr.GbSvrId;
                Req.m_DstId = Svr.GbSvrId;
                Req.m_Realm = Svr.GbSvrRealm;
                Req.m_Expires = Svr.Expires;
                RegisterUpServer(Req);
            }, 5 * 1000, Svr.RegisterDelayer);
        }
    });
}

Uint32 CMkGbServer::NotifyDeviceNotifyAllUpServer(const CMkGbMessageRequest* pGbReq)
{
    MkMap<MkString, MkUpGbServer> MapUpSever;
    m_GbServerLock.RLock();
    MapUpSever = m_MapUpGbServer;
    m_GbServerLock.RUnlock();
    MkMap<MkString, MkUpGbServer>::iterator it = MapUpSever.begin();
    for (; it != MapUpSever.end(); it++) {
        m_pGb28181->MessageRequest(*pGbReq, nullptr);
    }
    return NoneError;
}

Uint32 CMkGbServer::DeviceAuthorSuccess(const MkString& RegisterId, const MkString& DeviceId, const MkString& DeviceHost, Uint16 DevicePort, BOOL bOnline)
{
    Uint32 ErrorCode = NoneError;
    if (bOnline) {
        ErrorCode = AddOnlineDevice(RegisterId, DeviceId, DeviceHost, DevicePort);
        if (NoneError != ErrorCode) {
            return NoneError;
        }
        //new register
        DeletePlayFromMediaServer(DeviceId);
        DeleteDeviceChildFromDevice(DeviceId);
        GetDeviceBasicConfig(DeviceId);

        CMkGbMessageRequest Req;
        Req.m_DstId = DeviceId;
        Req.m_DeviceId = DeviceId;
        Req.m_RouterId = DeviceId;
        Req.m_CmdType = "Catalog";
        Req.m_MessageType = "Query";
        m_pGb28181->MessageRequest(Req, [this, DeviceId](Uint32 ErrorCode, const CMkGbResponse* pRes) {
            const CMkGbMessageResponse* pMsgRes = dynamic_cast<const CMkGbMessageResponse*>(pRes);
            if (NoneError == ErrorCode) {
                MkVector<MkMapString> VecMapString;
                MkVector<MkGbMessage>::const_iterator it = pMsgRes->m_Message.VecChildren.begin();
                for (; it != pMsgRes->m_Message.VecChildren.end(); it++) {
                    VecMapString.emplace_back(it->MainParam);
                }
                UpdateMapCatalog(DeviceId, VecMapString);
            }
        });

        if (m_ConfigIni.GetProfileBoolean(GbAutoSubCatalog)) {
            CMkGbSubscribeRequest Req;
            Req.m_DstId = DeviceId;
            Req.m_RouterId = DeviceId;
            Req.m_DeviceId = DeviceId;
            Req.m_CmdType = "Catalog";
            Req.m_MessageType = "Query";
            Req.m_Expires = m_ConfigIni.GetProfileUint32(GbSubscribeExpries);
            Req.m_Event = "presence";
            //Req.m_Message.MainParam["StartTime"] = "";
            //Req.m_Message.MainParam["EndTime"] = "";
            m_pGb28181->SubscribeRequest(Req, [this](Uint32 ErrorCode, const CMkGbResponse* pRes) {
                MkInfoLog("catalog subscribe error:%d\n", ErrorCode);
            });
        }
    } else {
        DeleteOnlineDevice(DeviceId);
    }
    return NoneError;
}


MkString CMkGbServer::GetRequestStringValue(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkString& strKey)
{
    MkString strValue = JsonReq[strKey].asString();
    if (strValue.empty()) {
        MkMap<MkString, MkString>::const_iterator it = MapQuery.find(strKey);
        if (it != MapQuery.end()) {
            strValue = it->second;
        }
    }
    return strValue;
}

Uint32 CMkGbServer::GetRequestUint32Value(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkString& strKey)
{
    Uint32 uValue = 0;
    MkMap<MkString, MkString>::const_iterator it = MapQuery.find(strKey);
    if (it != MapQuery.end()) {
        uValue = CMkUtil::SafeAtoi(it->second.c_str());
    } else {
        uValue = JsonReq[strKey].asUInt();
    }
    return uValue;
}

float CMkGbServer::GetRequestFloatValue(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkString& strKey)
{
    float fValue;
    MkMap<MkString, MkString>::const_iterator it = MapQuery.find(strKey);
    if (it != MapQuery.end()) {
        fValue = static_cast<float>(CMkUtil::SafeAtof(it->second.c_str()));
    } else {
        fValue = JsonReq[strKey].asFloat();
    }
    return fValue;
}

double CMkGbServer::GetRequestDoubleValue(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkString& strKey)
{
    double dValue;
    MkMap<MkString, MkString>::const_iterator it = MapQuery.find(strKey);
    if (it != MapQuery.end()) {
        dValue = CMkUtil::SafeAtof(it->second.c_str());
    } else {
        dValue = JsonReq[strKey].asFloat();
    }
    return dValue;
}

BOOL CMkGbServer::GetRequestBoolValue(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkString& strKey)
{
    BOOL bValue = FALSE;
    MkMap<MkString, MkString>::const_iterator it = MapQuery.find(strKey);
    if (it != MapQuery.end()) {
        bValue = "true" == it->second;
    } else {
        bValue = JsonReq[strKey].asBool();
    }
    return bValue;
}

Uint32 CMkGbServer::GetNotifyAction(const MkNotifyMessageType& ActionType, MkString& strType)
{
    MkUnorderedMap<Uint32, MkString>::iterator it = m_MapNotifyMsgType.find(ActionType);
    if (it == m_MapNotifyMsgType.end()) {
        MkErrorLog("input invalid notify message type:%d\n", ActionType);
        return InvalidParams;
    }
    strType = it->second;
    return NoneError;
}

Uint32 CMkGbServer::GetMkNofiyActionType(const MkString& StrType, MkNotifyMessageType& ActionType)
{
    MkUnorderedMap<Uint32, MkString>::const_iterator it = m_MapNotifyMsgType.begin();
    for (; it != m_MapNotifyMsgType.end(); it++) {
        if (StrType == it->second) {
            ActionType = (MkNotifyMessageType)it->first;
            return NoneError;
        }
    }
    return InvalidParams;
}

Uint32 CMkGbServer::ParseJsonContentToMapParam(const Json::Value& JsonParam, MkMapString& MapParam)
{
    Json::Value::Members member = JsonParam.getMemberNames();
    Json::Value::Members::iterator iter = member.begin();
    for (; iter != member.end(); iter++) {
        MapParam[*iter] = JsonParam[*iter].asString();
    }
    return NoneError;
}

Uint32 CMkGbServer::ParseJsonContentToInfoParam(const Json::Value& JsonParam, MkPair<MkString, MkString>& InfoParam)
{
    Json::Value::Members member = JsonParam.getMemberNames();
    Json::Value::Members::iterator iter = member.begin();
    if (iter != member.end()) {
        //only parse one item
        InfoParam.first = *iter;
        InfoParam.second = JsonParam[*iter].asString();
    }
    return NoneError;
}

Uint32 CMkGbServer::ParseJsonContentToGbMessage(const Json::Value& JsonContent, MkGbMessage& Message)
{
    Uint32 ErrorCode = NoneError;
    Json::Value::Members member = JsonContent.getMemberNames();
    Json::Value::Members::iterator iter = member.begin();
    for (; iter != member.end(); iter++) {
        Json::Value JsonItem = JsonContent[*iter];
        if (JsonItem.isArray()) {
            if ("Info" == *iter) {
                for (Json::ArrayIndex i = 0; i < JsonItem.size(); i++) {
                    MkPair<MkString, MkString> Info;
                    ErrorCode = ParseJsonContentToInfoParam(JsonItem[i], Info);
                    MkCheckErrorLog(ErrorCode, "parse info param failed\n");
                    Message.InfoParam.emplace_back(Info);
                }
            } else if ("SnapShotList" == *iter) {
                for (Json::ArrayIndex i = 0; i < JsonItem.size(); i++) {
                    MkPair<MkString, MkString> SnapShotInfo;
                    ErrorCode = ParseJsonContentToInfoParam(JsonItem[i], SnapShotInfo);
                    MkCheckErrorLog(ErrorCode, "parse info param failed\n");
                    Message.SnapShotParam.emplace_back(SnapShotInfo);
                }
            } else {
                Message.ChildKey = *iter;
                for (Json::ArrayIndex i = 0; i < JsonItem.size(); i++) {
                    MkGbMessage GbMsg;
                    ErrorCode = ParseJsonContentToGbMessage(JsonItem[i], GbMsg);
                    MkCheckErrorLog(ErrorCode, "parse child param failed\n");
                    Message.VecChildren.emplace_back(GbMsg);
                }
            }
        } else if (JsonItem.isObject()) {
            MkGbMessage GbMsg;
            ErrorCode = ParseJsonContentToGbMessage(JsonItem, GbMsg);
            MkCheckErrorLog(ErrorCode, "parse gb message param failed\n");
            if ("PTZCmd" == *iter) {
                MkString PtzCmd;
                ErrorCode = MapParamToGbPtzCmd(GbMsg.MainParam, PtzCmd);
                MkCheckErrorLog(ErrorCode, "parse ptz param failed\n");
                Message.MainParam["PTZCmd"] = PtzCmd;
            } else {
                Message.MapMessage[*iter] = GbMsg;
            }
        } else {
            if ("ItemName" == *iter) {
                Message.ItemName = JsonItem.asString();
            } else {
                Message.MainParam[*iter] = JsonItem.asString();
            }
        }
    }
    return NoneError;
}

Uint32 CMkGbServer::MapParamToGbPtzCmd(const MkMapString& MapParam, MkString& GbPtzCmd)
{
    MkMapString::const_iterator itCmdType = MapParam.find("CmdType");
    MkMapString::const_iterator itParam1 = MapParam.find("Param1");
    MkMapString::const_iterator itParam2 = MapParam.find("Param2");
    MkMapString::const_iterator itParam3 = MapParam.find("Param3");
    if (itCmdType == MapParam.end()
        || itParam1 == MapParam.end()
        || itParam2 == MapParam.end()
        || itParam3 == MapParam.end()) {
        return InvalidParams;
    }
    MkPtzCommand PtzCmd;
    MkGbPtzCommandType GbPtzCmdType;
    Uint32 ErrorCode = CMkPtzCommand::GetIntance().GetPtzCommand(itCmdType->second, PtzCmd);
    MkCheckErrorLog(ErrorCode, "input invalid cmd type:%s\n", itCmdType->second.c_str());
    ErrorCode = MkPtzCmdToGbPtzCmd(PtzCmd, GbPtzCmdType);
    MkCheckErrorLog(ErrorCode, "system ptz cmd to gb ptz cmd failed\n");
    CGbPtzCommand *pPtzCmd = CGbPtzCommand::CreateNew(GbPtzCmdType, std::stoi(itParam1->second), std::stoi(itParam2->second), std::stoi(itParam3->second));
    return pPtzCmd->ToGbString(GbPtzCmd);
}

Uint32 CMkGbServer::MkPtzCmdToGbPtzCmd(const MkPtzCommand& PtzCmd, MkGbPtzCommandType& GbPtzCmd)
{
    Uint32 ErrorCode = NoneError;
    switch (PtzCmd) {
    case MkPtzStop:
        GbPtzCmd = MkGbPtzStop;
        break;
    case MkPtzUp:
        GbPtzCmd = MkGbPtzUp;
        break;
    case MkPtzDown:
        GbPtzCmd = MkGbPtzDown;
        break;
    case MkPtzLeft:
        GbPtzCmd = MkGbPtzLeft;
        break;
    case MkPtzRight:
        GbPtzCmd = MkGbPtzRight;
        break;
    case MkPtzLeftUp:
        GbPtzCmd = MkGbPtzUp;
        break;
    case MkPtzRightUp:
        GbPtzCmd = MkGbPtzRightUp;
        break;
    case MkPtzLeftDown:
        GbPtzCmd = MkGbPtzLeftDown;
        break;
    case MkPtzRightDown:
        GbPtzCmd = MkGbPtzRightDown;
        break;
    case MkPtzHorseCtorAutoScan:
        GbPtzCmd = MkGbPtzRunAutoScan;
        break;
    case MkPtzVerseCtorAutoScan:
        GbPtzCmd = MkGbPtzRunAutoScan;
        break;
    case MkPtzZoomIn:
        GbPtzCmd = MkGbPtzZoomIn;
        break;
    case MkPtzZoomOut:
        GbPtzCmd = MkGbPtzZoomOut;
        break;
    case MkPtzFocusNear:
        GbPtzCmd = MkGbPtzNear;
        break;
    case MkPtzFocusFar:
        GbPtzCmd = MkGbPtzFar;
        break;
    case MkPtzApertureOpen:
        GbPtzCmd = MkGbPtzApertuerBig;
        break;
    case MkPtzApertureClose:
        GbPtzCmd = MkGbPtzApertuerSmall;
        break;
    case MkPtzLightTurnOn:
        GbPtzCmd = MkGbPtzSwithOn;
        break;
    case MkPtzLightTurnOff:
        GbPtzCmd = MkGbPtzSwitchOff;
        break;
    case MkPtzWiperTurnOn:
        GbPtzCmd = MkGbPtzSwithOn;
        break;
    case MkPtzWiperTurnOff:
        GbPtzCmd = MkGbPtzSwitchOff;
        break;
    case MkPtzFanTurnOn:
        GbPtzCmd = MkGbPtzSwithOn;
        break;
    case MkPtzFanTurnOff:
        GbPtzCmd = MkGbPtzSwitchOff;
        break;
    case MkPtzHeaterTurnOn:
        GbPtzCmd = MkGbPtzSwithOn;
        break;
    case MkPtzHeaterTurnOff:
        GbPtzCmd = MkGbPtzSwitchOff;
        break;
    case MkPtzAuxTurnOn:
        GbPtzCmd = MkGbPtzSwithOn;
        break;
    case MkPtzAuxTurnOff:
        GbPtzCmd = MkGbPtzSwitchOff;
        break;
    case MkPtzGotoPreset:
        GbPtzCmd = MkGbPtzCallPreset;
        break;
    case MkPtzSetPreset:
        GbPtzCmd = MkGbPtzSetPreset;
        break;
    case MkPtzDelPreset:
        GbPtzCmd = MkGbPtzClearPreset;
        break;
    case MkPtzCruiseFillPre:
        GbPtzCmd = MkGbPtzAddCruise;
        break;
    case MkPtzCruiseSetDwell:
        GbPtzCmd = MkGbPtzCruiseStayTime;
        break;
    case MkPtzCruiseSetSpeed:
        GbPtzCmd = MkGbPtzCruiseSpeed;
        break;
    case MkPtzCruiseClearPre:
        ErrorCode = UnSupported;
        break;
    case MkPtzCruiseRun:
        GbPtzCmd = MkGbPtzRunCruise;
        break;
    case MkPtzCruiseClear:
        GbPtzCmd = MkGbPtzDelCruise;
        break;
    case MkPtz3DZoom:
        break;
    default:
        break;
    }
    return ErrorCode;
}

Uint32 CMkGbServer::PacketMapParamToJson(const MkMapString& MapParam, Json::Value& JsonContent)
{
    MkMapString::const_iterator it = MapParam.begin();
    for (; it != MapParam.end(); it++) {
        JsonContent[it->first] = it->second;
    }
    return NoneError;
}

Uint32 CMkGbServer::PacketGbMessageToJson(const MkGbMessage& Message, Json::Value& JsonContent)
{
    PacketMapParamToJson(Message.MainParam, JsonContent);
    if (!Message.ChildKey.empty()
        && !Message.VecChildren.empty()) {
        Json::Value JsonChildren;
        MkVector<MkGbMessage>::const_iterator itVec = Message.VecChildren.begin();
        for (int i = 0; itVec != Message.VecChildren.end(); itVec++, i++) {
            PacketMapParamToJson(itVec->MainParam, JsonChildren[i]);
        }
        JsonContent[Message.ChildKey] = JsonChildren;
    }
    MkMap<MkString, struct _gb_message>::const_iterator itRes = Message.MapMessage.begin();
    for (; itRes != Message.MapMessage.end(); itRes++) {
        Json::Value JsonRes;
        PacketGbMessageToJson(itRes->second, JsonRes);
        JsonContent[itRes->first] = JsonRes;
    }
    return NoneError;
}

Uint32 CMkGbServer::ResponseHttp(const MkHttpResponseJsonCb& ResCb, Uint32 ErrorCode, const CMkGbResponse* pRes)
{
    Json::Value ResBody;
    if (pRes) {
        const CMkGbSubscribeResponse* pSubRes = dynamic_cast<const CMkGbSubscribeResponse*>(pRes);
        if (pSubRes) {
            ResBody["SubscribeId"] = pSubRes->m_SubscribeId;
        }
        PacketGbMessageToJson(pRes->m_Message, ResBody);
    }
    ResCb(ErrorCode, ResBody);
    return NoneError;
}

Uint32 CMkGbServer::PlayStream(const MkString &RouterId, const MkString& ChannelId, const CMkTime& BeginTime, const CMkTime& EndTime, const MkString& PlayType, const MkHttpResponseJsonCb& ResCb)
{
    MkString MediaServerId = GetFreeMediaServer();
    if (MediaServerId.empty()) {
        return MediaServerNotOnline;
    }
    MkString MediaPath;
    MkString Subject;
    if ("Play" == PlayType) {
        MediaPath = ChannelId;
        Json::Value ResBody;
        MkGbPlayParam Param;
        Uint32 ErrorCode = GetPlayInfo(MediaPath, Param);
        if (NoneError == ErrorCode) {
            ResBody["MediaServerID"] = Param.MediaServerId;
            ResBody["MediaPath"] = Param.MediaPath;
            ResBody["IsPlaying"] = Param.bPlaying;
            ResCb(NoneError, ResBody);
            return NoneError;
        }
        Subject = ChannelId + ":0,";
    } else {
        MkString RandomString = std::to_string(CMkUtil::GetRandomNumber());
        MediaPath = ChannelId + "_1" + RandomString;
        Subject = ChannelId + ":1" + RandomString + ",";
    }
    Subject += MediaServerId + ":" + std::to_string(CMkUtil::GetRandomNumber());
    MkGbPlayParam Param;
    Param.MediaPath = MediaPath;
    Param.MediaServerId = MediaServerId;
    Param.bPlaying = TRUE;
    m_PlayLock.WLock();
    m_MapPlay[MediaPath] = Param;
    m_PlayLock.WUnlock();
    return m_pGb28181->InviteRequest(MediaServerId, ChannelId, Subject, "", [this, RouterId, ChannelId, MediaServerId, PlayType, BeginTime, EndTime, Subject, MediaPath, ResCb](Uint32 ErrorCode, const CMkGbResponse* pResponse) {
        const CMkGbInviteResponse *pRes = dynamic_cast<const CMkGbInviteResponse*>(pResponse);
        if (!pRes || NoneError != ErrorCode) {
            DeletePlay(MediaPath);
            ResCb(SystemError, Json::Value());
            return;
        }
        CMkSdp OfferSdp;
        ErrorCode = OfferSdp.ParseContent(pRes->m_AnwserSdp);
        if (NoneError != ErrorCode) {
            DeletePlay(MediaPath);
            ResCb(SystemError, Json::Value());
            pRes->m_EventResCb(MkMapString(), "");
            return;
        }
        OfferSdp.SetSessionName(PlayType);
        if (!BeginTime.IsEmpty()) {
            OfferSdp.SetTime(CMkSdpTime(BeginTime.GetTvSec(), EndTime.GetTvSec(), MkVectorString()));
        }
        MkString strOfferSdp;
        ErrorCode = OfferSdp.ToString(strOfferSdp);
        if (NoneError != ErrorCode) {
            DeletePlay(MediaPath);
            ResCb(SystemError, Json::Value());
            pRes->m_EventResCb(MkMapString(), "");
            return;
        }
        EventResponseCallback EventCb = pRes->m_EventResCb;
        MkString ToMediaServerSession = pRes->m_SessionId;
        ErrorCode = m_pGb28181->InviteRequest(RouterId, ChannelId, Subject, strOfferSdp, [this, EventCb, RouterId, ChannelId, PlayType, BeginTime, EndTime, MediaPath, MediaServerId, ResCb, ToMediaServerSession](Uint32 ErrorCode, const CMkGbResponse* pResponse) {
            const CMkGbInviteResponse *pRes = dynamic_cast<const CMkGbInviteResponse*>(pResponse);
            if (!pRes) {
                return;
            }
            pRes->m_EventResCb(MkMapString(), "");
            EventCb(MkMapString(), pRes->m_AnwserSdp);
            if (NoneError != ErrorCode) {
                DeletePlay(MediaPath);
                ResCb(SystemError, Json::Value());
                m_pGb28181->ByeRequest(ToMediaServerSession, nullptr);
                return;
            }
            UpdatePlayParam(MediaPath, pRes->m_SessionId, ToMediaServerSession);
            Json::Value ResBody;
            ResBody["MediaServerID"] = MediaServerId;
            ResBody["MediaPath"] = MediaPath;
            ResCb(NoneError, ResBody);
        });
        if (NoneError != ErrorCode) {
            ResCb(ErrorCode, Json::Value());
        }
    });
}

Uint32 CMkGbServer::DeletePlay(const MkString& MediaPath)
{
    m_PlayLock.WLock();
    MkMap<MkString, MkGbPlayParam>::iterator it = m_MapPlay.find(MediaPath);
    if (it != m_MapPlay.end()) {
        m_MapPlay.erase(it);
    }
    m_PlayLock.WUnlock();
    return NoneError;
}

Uint32 CMkGbServer::GetPlayInfo(const MkString& MediaPath, MkGbPlayParam& Param)
{
    Uint32 ErrorCode = InvalidParams;
    m_PlayLock.RLock();
    MkMap<MkString, MkGbPlayParam>::iterator it = m_MapPlay.find(MediaPath);
    if (it != m_MapPlay.end()) {
        Param = it->second;
        ErrorCode = NoneError;
    }
    m_PlayLock.RUnlock();
    return ErrorCode;
}

Uint32 CMkGbServer::DeletePlayFromMediaServer(const MkString& MediaServerId)
{
    m_PlayLock.WLock();
    MkMap<MkString, MkGbPlayParam>::iterator it = m_MapPlay.begin();
    while (it != m_MapPlay.end()) {
        if (MediaServerId == it->second.MediaServerId) {
            it = m_MapPlay.erase(it);
        } else {
            it++;
        }
    }
    m_PlayLock.WUnlock();
    return NoneError;
}

Uint32 CMkGbServer::UpdatePlayParam(const MkString& MediaPath, const MkString& ToChannelSession, const MkString& ToMediaServerSession)
{
    m_PlayLock.WLock();
    MkMap<MkString, MkGbPlayParam>::iterator it = m_MapPlay.find(MediaPath);
    if (it != m_MapPlay.end()) {
        it->second.ToChannelSession = ToChannelSession;
        it->second.ToMediaServerSession = ToMediaServerSession;
        it->second.bPlaying = FALSE;
    }
    m_PlayLock.WUnlock();
    return NoneError;
}

CMkGbServer::~CMkGbServer()
{

}